پاسخ به:کلاس اموزش برنامه نویسی اندروید(دوره اول)
جمعه 3 بهمن 1393 1:56 AM
مقدمه بسیار مهم:
در این قسمت قصد دارم، مبانی و تعاریف اولیه شیء گرایی OO - Object Oriented * را بیان کنم. چرا که در عصر حاضر برنامه نویسی بدون دانستن این مفاهیم کاری بیهوده و غیر اصولی است. از طرف دیگر توضیح دادن بسیاری از مفاهیم برنامه نویسی جاوا و بالتبع اندروید نیازمند دانستن این مفاهیم است. لذا این قسمت را با صبر و حوصله مطالعه و آنرا مهم بدانید.
مفهوم شیء گرایی بر پایه ذات واقعی طبیعت که میراث بری است استوار است. اگر دنیای مادی را جامعه هدف مطالعات خود بگیریم، هر موجودی یک چیز است. شاید بهتر باشد از واژه چیز به Entity اشاره کنیم. در حالت کلی تر اگر هر Entity را یک Object بنامیم ( که در تئوری تفاوت هایی دارند ) آنگاه هر چیز یک Object است. لذا خواص کلی موجود در هر کلاس ( Class * ) از Object ها به سایر Object ی زیر مجموعه آن کلاس به ارث ( Inheritence * ) خواهد رسید.
بطور مثال اگر اشیاء جامد را Object در نظر بگیریم آنگاه کلاس هر Object دارای خواصی نظیر ( اندازه، وزن، مکان، جنس و ... ) است. حال اگر دسته ای از زیر شاخه های این کلاس را مانند وسایل الکترونیکی ElectronicDevice در نظر بگیریم آنگاه غیر از خواص فوق دارای خواص دیگری نظیر ( ولتاژ ورودی، میزان مصرف انرژی و ... ) هستند. حال اگر دسته های Computer را زیر مجموعه ElectronicDevice در نظر بگیریم علاوه بر خواص کلاس Object شامل اندازه و ... ، شامل خواص کلاس ElectronicDevice نظیر ولتاژ ورودی و ... هم هست علاوه بر اینکه می تواند خود دارای خواص ویژه ای نظیر Cpu Model, Ram Size , ... باشد. به همین ترتیب هر کلاس دیگری می تواند خواص والدین ( superclass یا parent ) خود را به ارث ببرد و خواص منحصر به فرد خودش را هم دارا باشد. به این خواص قابل اندازه گیری Field می گوییم.
علاوه بر Field ها که خواصی هستند قابل اندازه گیری مانند وزن و ...، می توان دستورالعمل هایی هم برای هر کلاس تعریف کرد که به آنها Method می گوییم. مثلاً در کلاس Object ، دستور العملی که به حرکت جسم منجر می شود را می توان یک Method دانست. چگونگی پیدایش، مردن، و ... هم می توانند Method های آن باشند. این دستورالعمل ها نیز مانند Field ها به کلاسهای زیرین ( subclass ) ها مثل ElectronicDevice قابل ارث بری هستند. اما ElectronicDevice هم برای خود دستورالعمل های منحصر به کلاسی دارد مثل چگونگی روشن شدن، خاموش شدن، کار کردن و ... . و همینطور در مثال Computer هم دستورالعمل های Boot شدن، Restart شدن و .... می توانند Method باشند. بنابراین یک Computer هم چون یک subclass از ElectronicDevice است، دستورالعمل های آن شامل روشن شدن، خاموش شدن، کار کردن را به ارث می برد و همینطور از Object یعنی چگونگی پیدایش، مردن، حرکت کردن و ...
تا اینجای کار همه چیز خوب و شفاف به نظر می رسد اما وقتی چالش های بیشتری در عمل بوجود می آید تعاریف ساده فوق به تنهایی پاسخگوی مشکلات نخواهند بود. بطور مثال اگر دو دسته از کلاس ها مانند ElectronicDevice, اشیاء دارای درب را دو کلاس متفاوت subclass ـی از Object در نظر بگیریم، آنگاه یک Laptop زیرکلاسی از کدام خواهد بود؟ نه می شود اشیاء درب دار را زیر کلاس ElectronicDevice در نظر گرفت نه بالعکس. از طرفی Laptop هر دو خواص را دارد. در اینجاست که مفاهیم دیگری از شیء گرایی مانند Interface * ها به کمک ما می آیند. و به همین ترتیب پیدا کردن راه حل مناسب برای مشکلات پیچیده تر نیازمند دانش گسترده تر در این باره خواهد بود.
به همین منظور ما ابتدا از تعاریف ساده شروع می کنیم و تا پایان آموزشها هر از چند گاهی که با چالش جدیتری مواجه می شویم، مفاهیم جدیدتری از شیء گرایی را بیان می کنیم تا مشکل ما را حل کند. پس از ساده ترین مفاهیم شروع خواهیم کرد.
آموزش:
در جاوا یک کلاس به نام Object وجود دارد که هر چیزی که تعریف می شود به طور پیش فرض subclass ـی از Object هست. برای تعرف یک کلاس جدید در Java به ترتیب زیر عمل می کنیم.
» بر روی AndroidCourse/src/com.uncocoder.course.lessons راست کلیک کنید و بزنید New->Class. توجه داشته باشید از این به بعد به عمل فوق می گوییم که یک کلاس در com.uncocoder.course.lessons بسازید.
» در پنجره باز شده فقط قسمت Name را پر کنید و بنویسید Vehicle ، همانطور که می بینید در قسمت Superclass نوشته است java.lang.Object . این همان کلاسی است که هر کلاس دیگر از آن میراث بری می کند. حال Finish بزنید. کدی که به شما نمایش داده می شود، همانطور که از محتویاتش پیداست، تعریف یک کلاس را در بردارد. خط اول آن نام پکیجی که کلاس در آن باید ساخته شود را تعیین می کند. توجه داشته باشید که نام فایل جاوای ساخته شده دقیقاً با نام کلاس یکی است و اگر قرار باشد نام کلاس عوض شود باید نام فایل هم عوض شود و بالعکس.
» کد Vehicle را به شکل زیر Edit کنید:
01 package com.uncocoder.course.lessons; 02 03 04 public class Vehicle .. 05 06 public float mPositionX = 0; 07 public float mPositionY = 0; 08 public float mPositionZ = 0; 09 10 public int mWeight = 0; 11 public float mSpeed = 0; 12 13 14 15 public Vehicle(float speed, int weight) .. 16 Log.i("LOG", "Vehicle Created with Speed: " + speed + ", Weight: " + weight); 17 mSpeed = speed; 18 mWeight = weight; 19 } 20 21 22 23 public void turnOn() .. 24 Log.i("LOG", "Vehicle Turned On"); 25 } 26 27 28 29 public void turnOff() .. 30 Log.i("LOG", "Vehicle Turned Off"); 31 } 32 33 34 35 public void startMove() .. 36 Log.i("LOG", "Vehicle Starts Moving"); 37 } 38 }
» با تغییر کد دور Log مربع خط چینی بوجود می آید و ناشی از این است که Eclipse با اجازه شما می خواهد PackageName مناسب کلاس Log را وارد برنامه کند. با نگه داشتن موس روی آن، پنجره ای باز می شود که دارای گزینه Import Log ( android.util است. شما این گزینه را انتخاب کنید. در نتیجه عبارت import android.util.Log به بالای فایل اضافه می شود. از این پس در صورت دیدن این مربع خط چین برای Log کار فوق را انجام دهید و در آموزشها، دیگر به آن اشاره نخواهد شد.
متغیرهای mPositionX, mPositionY, mPositionZ, mWeight, mSpeed همه همان Field هایی هستند که در بخش مقدمه از آن صحبت کردیم. و turnOn, turnOff, startMove متد هایی هستند که در بخش مقدمه در مورد آن صحبت کردیم. نام Vehicle که بالای turnOn نوشته شده است را Constructor * می گوییم. Constructor ها متدهای همنام با کلاس هستند که در پشت آنها عبارت void یا هر مقدار بازگشتی دیگر وجود نداشته باشد. هنگامیکه یک نمونه از کلاس ساخته می شود، این تابع در صورت وجود صدا زده می شود، اگر هم وجود نداشته باشد بازهم نمونه ساخته می شود اما بدون اینکه ما دخالتی در نحوه ساخت آن داشته باشیم.
» عبارت Log در هم خط باعث می شود در log خروجی پروژه اندروید متن دلخواه با استفاده از تگ LOG چاپ شود. برای دیدن این خروجی می توانید به نحوه زیر عمل کنید:
A: اگر این Tab در پنل پایین Eclipse موجود هست که روی آن کلیک کنید. اگر نه با رفتن به منوی Window->Open Perspective->Other گزینه All In One را انتخاب و OK بزنید.
B: با زدن این گزینه و وارد کردن LOG در دو کادر اول و زدن OK یک Filter جدید برای log ها خواهید ساخت که فقط پیامهایی را نشان می دهد که با تگ LOG در برنامه نوشته شده ارسال شده اند.
C: در صورتیکه برنامه به خطوط Log برسد، عبارات درج شده در پارامتر دوم این تابع، در این قسمت نمایش داده شود. اگر این اتفاق نیافتاد با رفتن به Devices در پنل سمت راست Eclipse و انتخاب emulator-5554 مشکل حل خواهد شد.
ویرایش: توجه داشته باشید که در این مرحله کلاس تعریف شده است ولی هیچ نمونه ای از آن ساخته نشده، در این شرایط انتظار نخواهیم داشت که Log ها در خروجی ثبت شوند چرا که هم اکنون، متد و دستوری باعث نمی شود که این خطوط اجرا شوند. با تغییر زیر می توانید یک نمونه از کلاس را ایجاد کنید و سرانجام خروجی Log ها را مشاهده نمایید.
کلاسها صرفاً یک الگو برای ساخت اشیاء هستند مثلاً می گوییم از جنس کامپیوتر، از جنس وسیله نقلیه و ... اما یک وسیله نقلیه یک نمونه ساخته شده از آن الگو ( یا همان کلاس است ). به این نمونه instance می گوییم. طریقه ساخت یک instance از کلاس Vehicle به طریقه زیر ممکن است. در پروژه قسمت سوم می خواهیم با کلیک شدن بر روی دکمه یک instance از Vehicle بسازیم. پس کاریهای زیر را انجام دهید:
» با باز کردن فایل AndroidCourseActivity.java متد initializeUi را به شکل زیر تغییر دهید:
01 private void initializeUi() .. 02 btn = (Button) findViewById(R.id.btn_action); 03 text = (TextView) findViewById(R.id.txt_caption); 04 05 btn.setOnClickListener(new OnClickListener() .. 06 07 @Override 08 public void onClick(View v) .. 09 text.setText("New String..."); 10 Vehicle myVehicle = new Vehicle(200f, 800); 11 myVehicle.turnOn(); 12 myVehicle.startMove(); 13 myVehicle.turnOff(); 14 } 15 }); 16 }
خط 10: یک نمونه از Vehicle را می سازیم. به علت اینکه Constructor این کلاس را بطوری تعریف کرده ایم که یک پارامتر float و یک int بگیرد، باید با همون الگوی ساخته شده آنرا صدا بزنیم، در غیر اینصورت Eclipse از کد ما خطا می گیرد.
خط 11: به نمونه ساخته شده می گوییم که turnOn کند
خط 12: به نمونه ساخته شده می گوییم که startMove کند
خط 13: به نمونه ساخته شده می گوییم که turnOff کند
توجه داشته باشید که با اجرای این برنامه و کلیک روی دکمه پنل LogCat لیست پیامهای ارسالی از سمت شما با استفاده از Log.i را نمایش می دهد.
حالا برای اینکه خواصی که این کلاس از Object به ارث برده است را ببینید داخل یکی از متد ها کلید Ctrl+Space را بزنید. پنجره زیر نمایش داده می شود:
متدها و فیلدهایی که دور آن کادر قرمز رنگ کشیده ام متعلق به کلاس Vehicle هستند که ما تعریف کرده ایم و اگر به آخرین کلمه در آن سطر توجه کنید این را در می یابید. اولین آیتم هم Constructor است که از Icon آن که شبیه یک C است مشخص می شود. باقی آیتم های این لیست از کلاس Object ارث بری شده اند که قابل استفاده در این کلاس هم می باشند. باز هم از کلمه آخر این لیست کلاس دربرگیرنده متد یا فیلد مشخص است. همینطور در این لیست نوع داده Field ها مثل float, int مشخص است. همینطور نوع برگشتی متد ها نیز مشخص است که ما برای همه متدها فعلاً void تعریف کرده ایم. به پنجره باز شده Code Completion یا Code Suggestion می گویند.
مفهوم Visibility:
» برای روشن شدن این مفهوم کد داخل Vehicle را به شکل زیر تغییر دهید.
01 package com.uncocoder.course.lessons; 02 03 import android.util.Log; 04 05 public class Vehicle .. 06 07 public float mPositionX = 0; 08 public float mPositionY = 0; 09 public float mPositionZ = 0; 10 11 public int mWeight = 0; 12 public float mSpeed = 0; 13 14 private int mType = 0; 15 16 17 18 public Vehicle(float speed, int weight) .. 19 Log.i("LOG", "Vehicle Created with Speed: " + speed + ", Weight: " + weight); 20 mSpeed = speed; 21 mWeight = weight; 22 } 23 24 25 26 public void setType(int type) .. 27 mType = type; 28 Log.i("LOG", "Vehicle Type Set!"); 29 } 30 31 32 33 public int getType() .. 34 Log.i("LOG", "Vehicle Type is: " + mType); 35 return mType; 36 } 37 38 39 40 public void turnOn() .. 41 Log.i("LOG", "Vehicle Turned On"); 42 } 43 44 45 46 public void turnOff() .. 47 Log.i("LOG", "Vehicle Turned Off"); 48 } 49 50 51 52 public void startMove() .. 53 Log.i("LOG", "Vehicle Starts Moving"); 54 } 55 }
خط 14: یک فیلد private تعریف کرده ایم و با استفاده از دو متد به نامهای setType و getType می توانیم آنرا با مقدار داده شده Set کنیم یا مقدار آنرا بخوانیم. توجه کنید که خروجی getType از نوع int است و همان نوعی است که mType دارد. با استفاده از عبارت return می توانیم مقداری را از متد به عنوان خروجی به سمت صدا زننده متد برگردانیم. اصطلاحاً به استفاده از دو متد با شکل و شمایل setType و getType می گویند Encapsulate کردن mType . حالا این چیست و چه کمکی به ما میکند و به Visibility چه ارتباطی دارد را با تغییر کد زیر می توان بهتر درک کرد.
» کد متد initializeUi کلاس AndroidCourseActivity را به شکل زیر تغییر دهید:
01 private void initializeUi() .. 02 btn = (Button) findViewById(R.id.btn_action); 03 text = (TextView) findViewById(R.id.txt_caption); 04 05 btn.setOnClickListener(new OnClickListener() .. 06 07 @Override 08 public void onClick(View v) .. 09 text.setText("New String..."); 10 Vehicle myVehicle = new Vehicle(200f, 800); 11 myVehicle.turnOn(); 12 myVehicle.startMove(); 13 myVehicle.turnOff(); 14 15 myVehicle.mPositionX = 10; 16 17 /* it's wrong code */ 18 //myVehicle.mType = 2; 19 20 myVehicle.setType(2); 21 Log.i("LOG", "My Vehicle Type is: " + myVehicle.getType()); 22 } 23 }); 24 }
همانطور که مشخص است در خط 15 توانستیم مقدار فیلد mPositionX را set کنیم اما همین کار را در خط 18 با فیلد mType نمی توانیم انجام دهیم و منجر به خطا از سمت Eclipse می شود. چرا که فیلد mPositionX یک فیلد Public ( عمومی ) است و از بیرون کلاس قابل خواندن و نوشتن است اما فیلد mType یک فیلد private ( خصوصی ) است و فقط از داخل خود آن کلاس قابل خواندن و نوشتن است. بنابراین با استفاده از متدهای setType, getType که هر دو public هستند می توانیم از بیرون کلاس مقدار mType را تحت تأثیر قرار دهیم. همانطور که در خطوط 20, 21 میبینید.
به این نوع دیدن متغیرها ( که گاهی مخفی و گاهی عمومی ) است Visibility می گوییم. همین شرایط در مورد متد ها هم برقرار است. یعنی می توانیم متدهای private تعریف کنیم که فقط از داخل کلاس قابل صدا زدن هستند و از بیرون قابل دید نیستند. اگر دقت کرده باشید turnOn, startMove, turnOff و همینطور Constructor دارای public visibility هستند و به این خاطر بود که توانستیم از خارج از کلاس آنها را صدا بزنیم.
حسن Visibility بسیار زیاد است شامل:
- محدود کردن کد، بنابراین سایر برنامه نویسان چیزهایی را می توانند تغییر دهند که ما اجازه داده ایم.
- حفظ کردن پایداری برنامه بدلیل محدود شدن برنامه نویس در شرایط گمراه کننده و انتخاب مسیر صحیح تر
- چک کردن مقادیر ورودی و سپس واریز آنها در متغیر
- انجام عملیات خاص در هنگام خواندن مقدار متغیر
- خلوت شدن لیستی از متغیر ها و متد ها و بنابراین راحتتر پیدا کردن اطلاعات لازم در code completion
- و بسیاری دیگر...
آموزش شیء گرایی مسیر بسیار مهم و طولانی خواهد بود. بنابراین با همین تعاریف کار کنید تا در یک مثال به این سادگی مشکلی وجود نداشته باشد. و منتظر آموزشهای بعدی در مورد شیء گرایی باشید.
سورس برنامه:
می توانید سورس را از آدرس زیر دانلود کنید:
توصیه ها:
- اگر با مفاهیم شیء گرایی ( Object Oriented * ) آشنایی لازم را ندارید بهتر است کتابی در مورد java تهیه و مطالعه کنید، با اینکه در این آموزشها با آن خواهیم پرداخت، اما مطالعه شما بهتر است.
- با همین مفاهیم اولیه در مورد شیء گرایی بسیار تمرین کنید و خود را در این مفاهیم قوی کنید تا در آموزشهای آتی بسیار راحتتر عمل کنید.
Android , iOS , Windowsphone , Symbian , Java, Mobile Review ,Learning