PDA

View Full Version : آموزش Object-oriented programming



mohammad272005
چهارشنبه 28 فروردین 1387, 01:36 صبح
سلام
تو این تاپیک من قصد دارم چیزایی رو که در مورد OOP می دونم بگم تا هم یه کمکی واسه تازه واردا بشه هم با مرور اطلاعاتم، اساتید محترم سایت اشکالات و نواقصم رو بهم گوشزد کنن.
زبونی هم که ازش استفاده می کنم C# 3.0 هست که امیدوارم هم من هم دوستان مفاهیم پایشو بدونیم که مشکل خاصی پیش نیاد. شاید انشاءالله یه روز هم C# 3.0 رو با هم مرور کنیم.
من تو نوشتن این مقاله میخوام از مفاهیم تکنیکی رو به زبون ساده تؤام با مثال توضیح بدم. بدیهیه که پیشنهادات و انتقادات (و 100 البته نظرات) شما دوستان میتونه در هرچه بهتر شدن این مقاله تاثیر مثبت بسزایی بزاره.
نکته: من دو سه سال پیش هم میخواستم این تاپیک رو تو فروم C++Builder بذارم ولی بخاطر پاره‏ای از مشکلات نشد.

mohammad272005
چهارشنبه 28 فروردین 1387, 01:47 صبح
programming یا OOP از طبیعت الهام گرفته یعنی میگه همه چیز تو این جان یه شئ هست. مثلا یک مداد یه شئ و یه کامیوتر هم همینطور.
اشیاء در ساده ترین حالت هیچ اجزا تشکیل دهنده‏ای ندارن. مثل عناصر ولی در حالتهای پیچیده‏تر می‏تونن در اجرای ساده‏تری تشکیل بشن. حتی اشیاء پیچیده تا ترکیب میتونن بازم اشیا پیچیده تری رو تشکیل بدن.

mohammad272005
چهارشنبه 28 فروردین 1387, 01:48 صبح
OOP بر پایه سه اصل استواره:

1- Inheritance
2- Polymorphism
3- Encapsulation

که حالا سعی می کنم با مثال هموشنو توضیح بدم.
اشیاء معمولا یک اسم جامعتری هم از اسم خودشون دارن. مثلا پژو یه ماشینه و بوئینگ یه هواپیماست. پژو و پراید و سمند همشون ماشنن. یه مثال قشنگتر اینکه 206 و 405 هردوشون پژو هستن و پژو یه وسیله نقلیه هست که خودرو هست (همه وسیله‏های نقلیه خودرو نیستن مثل دوچرخه) و یه خودرو یه ماشینه و دست آخر یه ماشین شیء هست. پس شد به این ترتیب:
206-> پژو -> وسیله نقلیه (خودرو) -> ماشین -> ... -> شیء
به این زنجیره اصطلاحا توارث یا inheritance گفته میشه.
ما از حالا تا اطلاعات ثانوی این اسم جامع اشیاء رو که خودش می تونه به یه شیء واقعی یا غیرواقعی اشاره کنه والد میگیم . برای مثال والد 206، پژو هست و والد پژو وسیله نقلیه. به این ترتیب والد تمام چیزها شئ هست. وقتی میگیم یه شیء از یه شیء والد ارث میبره یعنی تمام خصوصیات والد رو داره و امکان نداره که خصوصیتی از والد رو فرزند ارث نبره. در مثال قبلی گفتیم یه پژو یه ماشینه. پس تمام خصوصیات پایه‏ای رو که یه ماشین داره، پژرو هم به نوبه خودش داره مثلا 4تا چرخ داره، 4تا در داره، دارشون قفل میشن و ..... خوب پیکان هم ماشینه پس تمام امکان پایه یه ماشینو داره برای مثال اون هم مثل پژو دراش قفل میشه. ولی پیکان و پژو تو قفل شدن دراشون یکم با هم فرق دارن. مثل ممکنه قفل درای پژو برقی باشه ولی پیکان نه. پس یک شئ تمام خصوصیات والد رو داره ولی میتونه در صورتیکه والد بهش اجازه بده و خودشم دلش بخواد یه خورده نحوه عملکرد بعضی از خصوصیاتشو تغییر بده به این عمل میگیم چندوجهی بودن یا polymorphism.
از طرفی بازم تو مثال ما هیچوقت چیزی که به درد راننده نخوره در اختیارش قرار داده نمیشه. مثلا چندنفر از ما میدونیم نحوه عمل کردن فقل ماشینمون چطوریه؟ یا وقتی پدال گلز رو فشار میدیم چه اتفاقی میافته که چرخا به حرکت درمیان؟ اینکه چیزی رو که کاربر نهایی لازم نداره، شئ اون رو میپوشونه میگن encapsulation.

mohammad272005
جمعه 30 فروردین 1387, 23:21 عصر
با سلام مجدد
حالا نوبت یه بحثیه که من خودم شخصا (طبق برخی از مستندات، که الان یادم نیست) جزو OOP نمی‏دونم. پس یه خواهش کوچولو ازتون دارم. اونم
اینکه لطفا پاراگراف بعدی رو نخونید. مستقیم برید سر پاراگراف بعدیش. آخه این بحث رو تو فقط ++C میشه پیدا کرد و تو #C اثری ازش نیست. پس با
نخوندن پاراگراف بعدی هیچ چیزی رو از دست نمی‏دین.

mohammad272005
جمعه 30 فروردین 1387, 23:22 عصر
خوب به شما دوست شجاع تبریک میگم که بالاخره اومدی و خواستی این پاراگراف رو هم بخونی که دیگه هیچ چیز ناشنیده‏ای رو واسه خودت باقی
نذاری. به هرحال ما تو ++C یه مفهومی داریم به نام friend class که یعنی اونچه توی یک کلاس هست اعم از مخصوصی و غیرخصوصی (در مورد طبقه‏
بندی اعضا و خصوصیات بعدا میگم) رو یه کلاس بتونه بدون هیچ منع قانونی ببینه. خب به نظر من این خیلی بده. آخه اگه قراره کلاس دوم همه چیز رو
ببینه پس اصلا کلاس اول و دوم چرا دوتا موجود مجزا هستن؟

mohammad272005
جمعه 30 فروردین 1387, 23:41 عصر
از لحاظ طبقه‏بندی بر حسب جنس، اعضاء بر 4 قسمن که برحسب مثال خودمون از این قرارن: فرامین: مثل موقعی که شما استارت میزنین این یعنی
ماشین روشن شو. خصوصیات مثل نام، مدل، تعداد سیلندر و غیره، رویدادها مثل چراغهایی که روی کیلومترشمارن و شما رو از اتفاقات اعم از خوب (
مثل ارسال و انجام فرمان روشن شدن چراغا) و چه بد (مثل کم شدن روغن) مطلع میکنن. و در آخر صفات که خود شما بهش میدین مثل داشتن ضبط
CDدار و غیره.

mohammad272005
جمعه 30 فروردین 1387, 23:43 عصر
از لحاظ طبقه‏بندی بر حسب میزان دسترسی، اعضا بر 5 قسمن: خصوصی که بجز شرکت سازنده ماشین هیچکس ازش مطلع نیست. مثلا اطلاعاتی
که در پلاک لیزری ماشین موجوده. محافظت شده که توی همه ماشینا به نوعی هست و شما به عنوان راننده ازش بی‏اطلاعین مثلا طریقه کارکرد
داخلی ماشین. عمومی که در دسترس همه هست. مثل اطلاعات موجود روی کیلومترشما، کلیدهای صفحه‏کلید و غیره. داخلی که خاص ماشین
شماست و تو هیچ ماشین دیگه‏ای نیست مثل ضبطی برای این ماشین شما خریدید و در آخر محافظت شدة داخلی. مثل رمز لیزری روی سوییچ
ماشین هست و هیچ ماشین دیگه‏ای نداره.

mohammad272005
جمعه 30 فروردین 1387, 23:50 عصر
ببخشید!!! اصلا کسی این تاپیک رو میخونه؟ نه نظری نه تشکری نه پیشنهادی نه انتقادی! هیچی؟

تا بعد

Sajjad.Aghapour
شنبه 31 فروردین 1387, 00:12 صبح
ببخشید!!! اصلا کسی این تاپیک رو میخونه؟ نه نظری نه تشکری نه پیشنهادی نه انتقادی! هیچی؟

سلام
ممنون از وقتی که گذاشتید ....
چرا فکر می کنید کسی نمی خونه ؟!
اگه تا حالا هم کسی پیشنهاد یا انتقادی نکرده واسه اینه که تا اینجا پستهاتون چیز تازه ای نداشته.....
ولی چرا من یه پیشنهاد(ه یا انتقاد) دارم و اونم اینکه دارید تاپیکتون رو شلوغ می کنید.می تونستید 4 پست آخر رو توی یک پست بنویسید......
بازم ممنون

mohammad272005
سه شنبه 03 اردیبهشت 1387, 00:56 صبح
سلام
از الان به بعد دیگه بحثای تئوری فعلا کافیه. یکم هم عملی کار کنیم. درک می مطلب که ایجاد برای هر شئی حتما باید یه چیزی (هرچند ناملموس) شبیه قالب این شئ رو داشته‏باشیم خیلی مهمه. مثلا همون میدونیم توپ چیه. ولی به سرف تصور هر چیزی، این چیز خلق نمیشه. بلکه یک قالب ذهنی کمکون میکنه واسه خلق شئ. تو #C ما از کلمه کلیدی class استفاده میکنیم. یعنی –فعلا باختصار- مینویسیم:

class <ClassName>
{
{
مثلا

class Car
{
}
که یک ماشین رو تعریف مینکه.

mohammad272005
سه شنبه 03 اردیبهشت 1387, 00:58 صبح
همینطور که گفتیم تو طبیعت همه چیز از شئ ارث میره. یعنی تلویحا همه چیز یک شئ هست. تو #C هم این قانون استواره یعنی اگه ننویسیم که والد (parent) یه کلاس چیه، اون کلاس از Object که خوش یک کلاسه ارث میبره.
برای اینکه بتونیم توارث رو تو #C بنویسیم از علامت : استفاده می کنیم:

class <ClassName> [: <ParentClass>]
{
}
مثال:

class Peugeot : Car
{
}

mohammad272005
سه شنبه 03 اردیبهشت 1387, 01:07 صبح
خب تا اینجا قالب رو ساخیتم. میمونه خلق موجود. اونم به این ترتیبه:
ClassName instance = new ClassName();حالا یه نمونه (instance) از ClassName به نام instance داریم. مثال:
Peugeot myPeugeot = new Peugeot();اینطوری من یک Peugeot دارم. که از کلاس Car مشتق شده. این کلاس تمام اعضای Car رو (اگه عضوی داشته یاشه که فعلا نداره ارث می بره.حالا ببینیم چطوری میشه به این کلاسها عضو اصافه کرد.

mohammad272005
سه شنبه 03 اردیبهشت 1387, 01:08 صبح
حالا Peugeotی ما باید بدنه و موتور داشته باشه. این دو قطعه رو همه ماشینها دارن پس:

class Body
{
}
class Engine
{
}
class Car
{
Body _Body = new Body();
Engine _Engine = new Engine();
}

mohammad272005
سه شنبه 03 اردیبهشت 1387, 01:21 صبح
و مطلب مهم اینجاست که #C یه زبون Full Object Oriented هست یعنی شوخی نداره. اگه ما میزان دسترسی یک class modification یک شئ رو تعریف نکنیم، #C رهاش نمیکنه. اونه با class modification پیش‏فرض تعریف میکنه. class modification پیش‏فرض تو #C خصوصی یا private هست. در واقع _Body و _Engine هردو –فعلا- privateهستن. class modificationهای دیگه protected یا محافظت شده، public یا عمومی و internal یعنی داخلی هستن. private یعنی کلاس صاحب عضو، میتونه به اون عضو، دسترسی داسته باشه. مثل مثال بالا که فقط کلاس car میتونه _Body و _Engine رو ببینه. (البته یادتون هست که گفتین همه چیز parent به derivedش -کلاسی که از parent ارث برده- ارث میره. فقط derived نمیتونه ازش استفاده کنه.) protected یعنی اینکه عضو رو فقط parent و derivedها میتونن بصورت داخلی ببینن و instance نمیتونه. Public یعنی همه میتونن این ضو رو ببینن. internal یعنی فقط توی همون assemblyای که class تعریف شده قابل مشاهده هست و از بیرون قابل دسترسی نیست. ترکیبات منطقی بین class modificationهای فوق هم صحیحه. مثلا internal protected یعنی فقط derivedهای موجود در assembly جاری میتونن عضو رو ببینن.

mohammad272005
سه شنبه 03 اردیبهشت 1387, 01:27 صبح
با این تفاصیل _Body و _Engine باید چه class modificationی داشته باشن؟ بله درسته: public:

class Car
{
public Body _Body = new Body();
public Engine _Engine = new Engine();
}
چون ما می تونیم اونا رو از بیرون ببینیم
تا بعد

mohammad272005
شنبه 07 اردیبهشت 1387, 23:11 عصر
سلام
تو این جلسه باهم شروع میکنیم یکم روی اعضای یه کلاس دقیقتر شیم. اجزاء تشکیل دهنده یک کلاس رو عضو)member(های اون کلاس میگن. memberها چرا نوع هستن. فیلدها (fields)، خصوصیات (properties)، متدها (methods)، و رویدادها (events). که کم کم با همشون آشنا میشیم. البته توی OOP موجودات و مفاهیم دیگه‏ای هم هستن که انشاءالله اونها رو هم به مرور برسیم میکنیم. fieldها درست مثل متغیرهایی هستن که ما کاملا باهاشون آشنایی داریم. البته با دامنه حیاتی یکم بزرگتر از متغیرهای مورد استفاده تو روشهای اسپاگتی و پروسژورال (هر دو خارج ار بحث ما هستن).
میخوام از حالا به بعد یه کلاس ملموستر رو استفاده کنم. چون کلاسای بالا نمی تونن همه اونچه رو که میخوایم بهمون بدن. میخوام از کلاسی بنام Person استفاده کنم و به تدریج اونو کامل کنم. تا اینجا به یه تعریف ساده از این کلاس بسنده می کنم:

class Person
{
}

mohammad272005
شنبه 07 اردیبهشت 1387, 23:13 عصر
خب مسلما همه ما یه اسم واسه خودمون داریم. یعنی هر Personی یه Name داره. پس ما (در اینجا) میتونیم یه field به نام Name به این کلاسمون اضافه کنیم اونم ار نوع string:

class Person
{
public string Name;
}
یه اشکال خیلی بزرگی که field داره اینه: (ببینین خودتون میتونین متوجه بشین؟ )

Person person = new Person();
person.Name = "Ali";
person.Name = "Reza";

mohammad272005
شنبه 07 اردیبهشت 1387, 23:27 عصر
خب میگه میشه اسم هرکسی رو هر وقت دلمون خواست عوض کنیم؟ یه راه بهتر لازمه. چیزی که فقط یه بار تنظیم بشه. در ضمن برای نامگذاری آدما یه قانون دیگه هم است. هیچ کس تو 40سالگی نامگذاری نمیشه. در لحظه تولد (حالا یکم قبلتر یا بعدتر) این عمل انجام میشه. برای این منظور ما با دوتا مفهوم آشنا میشیم به نامهای سازنده یا constructor و فیلد فقط خواندنی یا readonly. یه بار دیگه برگردید به جایی که از کلاسمون Instance گرفتیم:

Person person = new Person();برای خلق یه کلاس از یه متدی استفاده می کنیم که (ظاهرا) وجود نداره (در مثال ما Person()) به این متد اصطلاحا میگن constructor که برای ما از کلاسمون یکی درست می کنه. خب ما میتونیم واقعا داشته باشیمش.


class Person
{

public Person()
{
}
}

جالب شد. خب چرا از این متد واسه نامگذاری استفاده نکنیم؟

class Person
{
public string Name;
public Person()
{
this.Name = "Ali";
}
}حالا کلاسمون به محض تولد یه اسم داره.

mohammad272005
شنبه 07 اردیبهشت 1387, 23:29 عصر
نکته: کلمه کلیدی this یعنی همین instanceی که توش قرار داریم. هم خانواده این کلمه، کلمه base هست که به parent کلاس جاری اشاره می کنه. البته گفتیم که تمام memberهای parent رو derived ارث می بره. پس base به چه درد میخوره؟ عجله نکنید. میرسیم.

mohammad272005
شنبه 07 اردیبهشت 1387, 23:37 عصر
ولی اینجا یه اشکالی هست. کی تا حالا نوزادی رو دیده که خودش واسه خوش اسم بزاره؟ باید یه طوری این اسم رو از بیرون به خورد کلاس بدیم. راه حل این مشکل دادن پارامتر به constructor هست. یعنی:

class Person
{
public string Name;
public Person(string name)
{
this.Name = name;
}
}
حالا بهتر شد. به این ترتیب برای ایجاد یه person باید اینطوری عمل کرد:

Person person = new Person("Ali");تا بعد.

mohammad272005
یک شنبه 15 اردیبهشت 1387, 23:14 عصر
سلام و تشكز از دانيال جان بابت راهنماييشون.
تا اينجا تونستيم با يه constructor پارامتريك، personمون رو نامگذاري كنيم. ولي هنوز مشكل اصليه باقيه. اونم اينه كه بعد از instanceگيري از person (شخص متولدشده) ديگه نبايد بشه اسم person رو عوض كرد. حالا چطوري؟ اينكار به تعداد انسانها راه داره. راه حل ما فعلا يه فيلد readonly هست. اينطوري:


public readonly string Name;
حالا ديگه خارج از constructor (حتي تو خود كلاس) عمرا كسي نمي تونه اين person رو نامگذاري كنه. چون:
A readonly field cannot be assigned to (except in a constructor or a variable initializer)تا حالا constructor بدون پارامتر (parameterless) و باپارامتر (parametric)، فيلد (field) و فيلد فقط خواندني رو (readonly field) رو ديديم. ميرسيم سر يكي از بحثاي مورد علاقه من: property.
هر كسي واسه خودش يه سني داره. پس اين person ما هم بايد مجهز به age باشه. يعني يه چيزي مثل اين:

public int Age;
همونطوري كه ميدونيم به اين ميگن يه فيلد. يه فيلد هيچ اختياري جز data-type از خودش نداره يعني فقط اجازه نميده مقداري مثل Hassan رو بهش بدن. مثلا سن كي متونه -10 يا 2050 باشه؟ خب فيلد كه نميتونه اينو كنترل كنه. پس بايد چيكار كرد؟ يه solution ساده اينه كه فيلد age رو private كنيم و دوتا متد مثلا به نامهاي GetAge و SetAge بصورت زير بنويسيم:

private int _Age;
public int GetAge()
{
return this._Age;
}
public void SetAge(int age)
{
if (age > 0 && age < 100)
this._Age = age;
}
حالا فرض كنيد يه كلاس 20 تا از اين فيلدها داشته باشه. يك فيلد + 2متد بازاي هر فيلد = 60 عضو. اين به نظر ما زياد نيست؟ اينجاست كه property به كمكمون مياد:
property يا خصوصيت قادره تا حدي خودشو كنترل كنه. property در واقع از يك يا تركيب دو متد ايجاد ميشه. كه هردو متد اختياري هستن. ولي حداقل يكي بايد باشه.
در حالت كلي، property اينجوري تعريف ميشه:
[class modifier[s]] [type] PropertyName
{
get{ return field; }
set{ field = value; }
}
مثلا age رو ميشه اينطوري نوشت:

private int _Age;
public int Age
{
get
{
return _Age;
}
set
{
_Age = value;
}
}
جالب شد. پس حالا كاراي كنترلي رو كجا بنويسيم؟ دقيقا همونجا كه ميخوايم فيلد _Age رو مقدار بديم. يعني اينجوري:

private int _Age;
public int Age
{
get
{
return _Age;
}
set
{
if (value > 0 && value < 100)
_Age = value;
}
}
رسيديم به جواب. فقط در مورد proprty يه سري چيزاي جالبي هم هست كه بعضياشو تلويحا گفتم و به مرور سعي ميكنم كاملترش كنم.
(نظر يادتون نره)
تا بعد

Mahdi.Kiani
یک شنبه 15 اردیبهشت 1387, 23:39 عصر
(نظر يادتون نره)
تا بعد

سلام آقا محمد و خسته نباشین
دیدم زیاد اسرار کردین که نظر بدن دوستان، دارم توی تاپیکتون پست میزنم. چون خودم به شدت نسبت به پست های متفرقه و .. در یک تاپیک آموزشی آلرژی شدید دارم چون تاپیک را از مسیر خودش خارج می کنه. از ظرفی هم خواستم با پیغام خصوصی نظرم را بگم ولی ناچارا اینجا میذارم که دیگر دوستان هم ببینند ( چنانچه در پایان پست بنده تصمیماتی در جهت روند آموزشتون گرفتید، پست من و دیگر پست های متفرقه این تاپیک می تونه با همکاری آقای امیر شکاری پاک بشه)
و اما ...
1) همانطور که بعضا هم اشاره شد، از تاپیک های کوتاه و یک خطی یا دو خطی خود داری کنید.. این گونه تاپیک ها نه تنها رغبت خواننده را به مطالب زیاد نمیکنه بلکه کم هم می کنه.. شاید بیش از 10 پست شما در این تاپیک، قابل ادغام در یک پست هستند..
2)به هیچ عنوان از دوستان و کاربران نخواهید که نظر بدهند( منظورم در خود تاپیک است) دلیلش را هم که گفتم ( بی نظمی در تاپیک و شلوغ شدن های بی مورد تاپیک و ...)
تبصره : دوستانی که می خواهند هر گونه، نظر، پیشنهاد سوال و یا هر چیز دیگری را با پیغام خصوصی با شما در میان بگذارند و یا در یک تاپیک جدا ( اگر سوال یا نظر کاربر ارزش ایجاد تاپیک را داشته باشه) با شما در میان بگذارند.
3)اگر قصدتان آموزش هست، که یقینا همینطوره خیلی نگران فید بک کاربران نباشید. تجربه های زیادی ثابت کرده که بعضی از کاربران حتی زحمت کلیک کردن بر روی یک دکمه را هم به خودشون نمی دهند. پس نگران این موضوع نباشید.
4) واقعا احساس کنید که دارید آموزش می دهید !!!
5)مطالبتون را دسته بندی کنید، و سعی کنید که شاخه به شاخه نپرید و حتی المقدور همراه با نمونه کد بذارین ( تجربه نشان داده که بعضی از کاربران این جوری بیشتر حال می کنند)
6) این خیلی خوب هست که مطالب را از مقدماتی شروع کرده اید، چون با عث میشه کاربران مبتدی هم بتوانند از مطالب شما استفاده کنند. ولی سعی کنید که مطالب ساده را سریعتر پیش برید و به مسائلی بپردازید که کاربران اکثرا با اونا مشکل دارند.
****
موفق باشید

mohammad272005
دوشنبه 23 اردیبهشت 1387, 21:25 عصر
سلام
اولين مورد در مورد propertyها دسته بندي اخلاقي اونهاست. كه بصورت زير انجام ميشه:
1- Read/write
مثل Age خودمون
2- Read only
مثل اين:

private string _Name = "default read only name";
public string Name
{
get
{
return _Name;
}
}
3- Write only
مثل اين:

private string _Name = "default write only name";
public string Name
{
set
{
_Name = value;
}
}
واضحه كه ما معمولا از نوع سوم استفاده نمي كنيم.
توي C# 3.0 يه نوع property ديگه هم است كه در واقع با نوع اول از نظر كاركرد هيچ فرقي نمي كنه. و اون Automatically Implemented Property هست:

public int Age
{
get;
set;
}
مزيت اين نوع property بر نوع اول اينه كه نيازي به private field نداره. (نكته: گاهي به private field عبارت backing field هم اتلاق ميشه.) البته ناگفته نمونه كه backing field توسط CLR تدارك ديده مي شه و در دامنه دسترسي ما نيست.
در NET 2.0 يه چيزه جالب اضافه شد كه من شخصا حس كردم يه قدم ديگه به (nature oriented) –من درآوردي بود- نزديكتر شديم. افزودن class modifier به get و set. مثال:

public int Age
{
get;
private set;
}
اينطوري بكل نياز ما به backing field مرتفع ميشه. فقط بايد يادمون باشه كه #C به استفاده نامعقول گير ميده. مثلا

private int Age
{
get;
public set;
}
اين error رو ميده:
Error 1 The accessibility modifier of the 'ConsoleApplication236.Program.Age.set' accessor must be more restrictive than the property or indexer 'ConsoleApplication236.Program.Age' F:\Programming\Temp\ConsoleApplication236\ConsoleA pplication32\Program.cs 13 20 ConsoleApplication236
راست ميگه خب معني نداره يه property كه از بيرون بهش access نيست متد setش public باشه.
تا بعد