Borna66
03-15-2009, 07:54 PM
مقدمه
در دنیایی واقعی . انسانها اشیا را کلاسه بندی می کنند و از این طریق بهتر پی به خصوصیات اشیا و وابستگی آنها میبرند . ذهن انسان به سمت ساختن یک ساختار درختی برای اشیا و رده بندی آنها و حفظ و نگهداری خصوصیات هر رده آموزش داده شده است .
برای مثال کلاس موجودات زنده به دو زیر کلاس بزرک گیاهان و جانوران تقسیم می شود . جانوران نیز خود به زیر کلاس های مهره داران و بی مهرگان تفکیک می گردند . پستانداران یکی از زیر کلاسهای کلاس مهره داران است . و انسان زیر کلاسی از پستان داران را تشکیل می ده . کلاس موجودات زنده دارای صفاتی است که این صفات در تمام آنها مشترک است . از این صفات می توان تنفس . تغذیه و رشد را نام برد . زیر کلاس جانوران علاوه بر صفات کلاس موجودات زنده صفات خاص خود را نیز دارند . از این صفات حرکت و تولید مثل را میتوان ذکر کرد . این روند برای زیر کلاسهای پایین تر می تواند ادامه پیدا کند .
اگر دید حاکم بر تحلیل و طراحی یک سیستم نرم افزاری به گونه ای باشد که سیستم را به عنوان یک کلاس ببیند که دارای توانایی انجام تعدادی فعالییت است و این فعالییت ها بر روی نوع داده ای انجام می شود . و سیستم به چند زیر سیستم تقسیم می شود و هر زیر سیستم مشابه سیستم اولیه متشکل از تعدادی فعالیت و تعدادی نوع دادهای باشد و این کار به قدر کافی ادامه پیدا کند . آنگاه تحلیل و طراحی از نوع شی گرا خواهد بود . پیاده سازی چنین طرحی نیاز به ابزار خاص خود دارد . برنامه سازی با به کار گیری این ابزار به صورت علمی و اصولی در پیاده سازی طرح مورد نظر . برنامه سازی شی گرا نامیده می شود . برای برنامه سازی شی گرا ابتدا باید با مفاهیم شی گرایی آشنایی کامل پیدا کرد . برای درک بهتر این مفهوم در مقدمه دو مفهوم کلاس و شی را به اختصار توضیح می دهیم .
کلاس
کلاس روشی برای بسته بندی نوع داده مجرد است . در کلاس امکان بسته بندی و محصور کردن (Encapsulation ) مجموعه ای از داده ها . روال های پردازش کننده این داده ها را به صورت یک بسته واحد فراهم می کند .
داده های داخل یک کلاس به وسیله کلاس محافظتمی گردد . به گونه ای که پردازش داده های خصوصی یک کلاس تنها از طریق روال های داخلی آن امکان پذیر است . داده های یک کلاس را متغیر های کلاس و روال های آن را روش نامیده اند . برای مثال . کلاس انسان ها یک کلاس قابل تعریف است . در این کلاس خصوصیات مشترک انسان ها تعریف می گردد و هیچ انسان خاصی را نشان نمی دهد . کلاس یک نوع است . همانگونه که مثلا int یک نوع است .
عملیات محاسباتی ( یا غیر محاسباتی ) بر روی نوع داده انجام نمی شود . بلکه این عملیات بر روی متغیرهایی که از این نوع داده تعریف می گردد انجام می شود . بطور مشابه عملیات محاسباتی ( یا غیر محاسباتی ) روی کلاس انجام نمی شود .
شیء
یک شی یک نمونه واقعی از یک کلاس است . همانگونه که در C (زبان غیر شی گرا ) می توان متغیر یا متغیر هایی از یک نوع مثلا int تعریف کرد و این متغیر هارا پردازش نمود . در یک زبان شی گرا میتوان شی یا اشیایی را از یک کلاس تعریف کرد . این اشیا موجودیت واقعی پیدا می کنند و قابل پردازش هستند . همانطور که یک انسان خاص . از کلاس انسانها موجودیت واقعی پیدا می کند و فعالیت می کند تغذیه می کند و… در چارچوب یک زبان شی گرا به متغیر های یک نوع داده نیز اشیا میگویند . هر شی داده مخصوص به خود دارد که متغیر های عضو یا داده های عضو نامیده می شوند .
تاریخچه
دیدگاه شیگرایی (Object Oriented) از اواسط دهه ۱۹۷۰ تا اواخر دهه ۱۹۸۰ در حال مطرح شدن بود. در این دوران تلاشهای زیادی برای ایجاد روشهای تحلیل و طراحی شیگرا صورت پذیرفت. در نتیجة این تلاشها بود که در طول ۵ سال یعنی ۱۹۸۹ تا ۱۹۹۴، تعداد متدولوژیهای شیگرا از کمتر از ۱۰ متدولوژی به بیش از ۵۰ متدولوژی رسید. تکثر متدولوژیها و زبانهای شیگرایی و رقابت بین اینها به حدی بود که این دوران به عنوان “جنگ متدولوژیها” لقب گرفت. از جمله متدولوژیهای پرکاربرد آن زمان میتوان از Booch، OOSE، OMT، Fusion، Coad-Yourdan، Shlayer-Mellor وغیره نام برد. فراوانی و اشباع متدولوژیها و روشهای شیگرایی و نیز نبودن یک زبان مدلسازی استاندارد، باعث مشکلات فراوانی شده بود. از یک طرف کاربران از متدولوژیهای موجود خسته شده بودند، زیرا مجبور بودند از میان روشهای مختلف شبیه به هم که تفاوت کمی در قدرت و قابلیت داشتند یکی را انتخاب کنند. بسیاری از این روشها، مفاهیم مشترک شیگرایی را در قالبهای مختلف بیان میکردند که این واگرایی و نبودن توافق میان این زبانها، کاربران تازهکار را از دنیای شیگرایی زده میکرد و آنها را از این حیطه دور میساخت. عدم وجود یک زبان استاندارد، برای فروشندگان محصولات نرمافزاری نیز مشکلات زیادی ایجاد کرده بود.
***
در این تحقیق شی گرایی را در دو زبان برنامه نویسی ( C++ و C# ) مورد بررسی قرار می دهم و شی گرایی و موارد آن را در هر یک به اختصار توضیح می دهم .
در ابتدا نگاهی می اندازیم به این خاصیت در زبان برنامه نویسی C++ و در ادامه شی گرایی را در زبان C# مورد بررسی قرار میدهیم وسپس لیست برخی از برنامه های شی گرا را ذکر می کنیم .
شی گرایی در زبان C++
برنامه نویسی شی گرا چیست ؟
از آنجایی که اساس تکوین c++ برنامه نویسی شی گرا است . پس مهم است که تعریف دقیقی را از برنامه نویسی شی گرا ارائه دهیم . شی گرا از بهترین مفاهیم برنامه سازی ساخت یافته بوجود آمده است و با چندین مفهوم قوی ترکیب شده که امکان سازماندهی برمانه ها به طور کارامد را فراهم می کند . به طور کلی هنگامی که در حالتی شی گرا نیز برنامه می نویسید مساله را به بخش های تشکیل دهنده آن تجزیه می کنید . هر مولفه ای یک شی خود ظرف می شود . که شامل دستور العملهای خودش و داده های مرتبط به آن شی است . از طریق این عملیات پیچیدگی کاهش یافته و می توان برنامه های بزرگ را مدیریت کرد . همه زبان های برنامه نویسی شی گرا در سه چیز مشترک هستند : کپسوله سازی . چند ریختی و وراثت . که در زیر اشاره مختصری به هر یک از آنها می کنیم .
کپسوله سازی
همانطوری که میدانید تمام برنامه ها از دو عنصور اصلی تشکیل می شوند : عبارت برنامه ( کد ) و داده ها . کد بخشی از برنامه است که عملیات را اجرا می کند و داده ها اطلاعاتی است که توسط این عملیات تحت تاثیر قرارگرفته . کپسوله سازی یک مکانیزم برنامه نویسی است که کد و داده را با هم در یک جا قرار داده و هر دو را از استفاده نادرست وتداخل خارجی ایمن نگه می دارد.
در یک زبان شی گرا . کد و داده ممکن است باهم در چنین روشی محدود شوند که یک جعبه سیاه خود ظرف را ایجاد می کند . درون جعبه تمام داده های مورد نیلز و کد است . هنگامی که در این روش کر و داده ها با هم پیوند برقرار می کنند . یک شی به وجود می آید . به عبارت دیگر . یک شی ابزاری است که از کپسوله سازی پشتیبانی می کند .
درون یک شی ( کد و داده ها ) یا هر دو ممکن است برای آن شی محلی ( خصوصی / private ) یا عمومی ( public ) باشند . کد یا داده های محلی فقط توسط بخش دیگری از شی شناخته شده و قابل دست یابی هستند .
به همین دلیل کد یا داده محلی برای قطعه ای از برنامه که خاج از شی است . قابل دسترس نمی باشد . هنگامی که کد یا داده ها عمومی هستند بخشهای دیگری از برنامه ممکن است به آنها دسترسی داشته باشند حتی اگر درون شی تعریف شده باشند بخش های عمومی یک شی برای ارائه یک ارتباط کنترل شده با عناصر محلی شی مورد استفاده قرار می گیرند .
چند ریختی
چند ریختی کمیتی است که به یک رابط امکان می دهد تا برای یک کلاس عمومی از عملیات مورد استفاده قرار گیرد . عمل خاص توسط ذات حقیقی شی تعیین می شود . یک مثال ساده از چند ریختی در فرمان اتومبیل است . فرمان اتومبیل برای تمام اتومبیل ها بدون توجه به مکانیزمی که مورد استفاده قرار می دهند یکسان است . فرممان برای اتومبیلی که به صورت دستی کار میکند یا با نیروی برق یا هر چیز دیگری عمل یکسانی را انجام میدهد . بنابراین بعد از اینکه شما چگونگی عمل کردن فرمان را یاد گرفتید میتوانید هر نوع اتومبیلی را برانید . همین هدف نیز می تواند در برنامه نویسی اعمال شود . به عنوان مثال یک پشته ( لیستی که در آن اولین ورودی آخرین خروجی است مثل تعدادی سکه که روی هم قرار می گیرند ) را در نظر بگیرید. ممکن است برنامهای داشته باشید که نیاز به سه نوع مختلف پشته داشته باشد یک پشته برای مقادیر اعداد صحیح . یک پشته برای اعداد اعشاری و یک پشته برای کاراکترها مورد استفاده قرار گیرد . در این صورت الگوریتمی که هر سه پشته را پیاده می کند یکسان است حتی اگر داده هایی که در آنها ذخیره می شود متفاوت باشند . در یک زبان غیر شی گرا نیاز خواهید داشت تا سه نوع مختلف از روال ها ی پشته را ایجاد کرده . به هر کدام نام متفاوتی قرار داده و برای هر کدام از روابط خاص خودش استفاده کنید . به دلیل وجود چند ریختی در C++ می توانید یک مجموعه روال عمومی از پشته ایجاد کرده و آن را برای هر سه نوع به کار ببرید . با این روش بعد از اینکه استفاده از یک پشته را یاد گرفتید می توانید همه انواع آن را به کار ببرید .
به طور کلی مفهوم چند ریختی اغلب توسط عبارت ” یک رابط. چندین روش ” بیان می شود . این بدین معنی است که امکان طراحی یک رابط عمومی برای گروهی از عملیات مرتبط وجود دارد .
چند ریختی با اعمال رابط یکسانی که برای تعیین یک کلاس عمومی مورد استفاده قرار می گیرد . به کاهش پیچیدگی کمک می کند . این است وظیفه کامپایلر تا فعالیت خاصی ( مثل متد ) را برای اعمال روی آن انتخاب کند . شما به عنوان برنامه نویس نیاز ندارید تا این انتخاب را انجام دهید شما فقط نیاز دارید رابط عمومی را به خاطر سپرده و استفاده کنید .
زبان های برنامه نویسی شی گرای اولیه چون به صورت مفسری بودند از چند ریختی در زمان اجرا پشتیبانی می کردند . ولی چون C++ کامپایلری است پس هم در زمان اجرا و هم زمان کامپایل از چند ریختی پشتیبانی می کند.
وراثت
وراثت . عملی است که یک شی می تواند مشخصه های شی دیگری را بدست آورد . به همین دلیل از مفهوم دسته بندی سلسله مراتبی پشتیبانی می کند . اگر در رابطه با وراثت بیشتر فکر کنید اطلاعات بیشتری راجع به دسته بندی سلسله مراتبی ( از بالا به پایین ) بدست خواهید آورد . به عنوان مثال سیب قرمز بخشی از دسته بندی سیب که آن هم بخشی از کلاس میوه هاست که آن هم در کلاس بزرگتری به نام غذا قرار دارد . کلاس غذا دارای مشخصات اصلی ( خوراکی . پروتئین و غیره ) است که به طور منطقی به زیر کلاس های غذا اعمال می شود . علاوی بر این مشخصات کلاس میوه دارای مشخصه های ( آبدار. شیرین و غیره ) است که آن را از سایر غذا ها متمایز می کند . کلاس سیب نیز مشخصه های خاصی را برای یک سیب تعریف می کند که عبارتند از : رسیدن روی درخت و غیره . یک سیب قرمز تمام خصوصیات کلاسهای بالاتر را به ارث می برد و فقط مشخصه هایی که منحصر به فرد هستند را تعریف خواهیم کرد .
بدون استفاده از وراثت هرشی به طور مجزا بایستی تمام مشخصه های خودش
را تعریف کند .با استفاده از وراثت شی فقط نیاز به تعریف مشخصه هایی دارد که در داخل آن کلاس منحصر به فرد هستند . این سبب می شود که صفات عمومی را از پدرشان به ارث ببرند .
بنابراین . مکانیزم وراثت به یک شی امکان میدهد تا نمونه خاصا از یک حالت عمومی تر باشد .
C++ برنامه نویسی شی گرا را پیاده سازی می کند .
چندین ویژگی در C++ وجود دارد که از کپسوله سازی . چند ریختی و وراثت پشتیبانی می کنند. به خاطر داشته باشید که می توانید از C++ برای نوشتن هر نوع برنامه ای و با استفاده از هر نوع روشی استفاده کنید . این مطلب کهC++ از OOP پشتیبانی می کند بدین معنی نیست که فقط می توانید برنامه های شی گرا بنویسید . همانند پیشینه خود ( یعنیc ) یکی از قویترین مزایای C++ قابلیت انعطاف آن است .
شی گرایی در زبان C#
شئ گرایی (OOP) در #C بر چند پایه استوار است که به قرار زیرند:
- Inheritance
- Encapsulation
- Polymorphism
- Abstraction
- Interface
اکنون به توضیح مختصر هر یک می پردازیم.
Inheritance ارث بری
پدر و فرزندی را در نظر بگیرید. هر پدری مشخصات فردی به خصوصی دارد. فرزند وی می تواند همه خصوصیات او را به ارث برد و خصوصیتهای دیگری نیز داشته باشد که پدرش ندارد. این یعنی ارث بری! برای مثال پدر وقتی عصبانی می شود، داد و فریاد می کند. پسر هم این خصوصیت را به ارث می برد با این تفاوت که وقتی عصبانی می شود، علاوه بر داد زدن، چند عدد بشقاب هم می شکند. در برنامه نویسی شئ گرا از مفهوم ارث بری استفاده های زیادی می شود. برای تفهیم راحت تر مسئله فرض کنید کلاسی به نام وسیله نقلیه داریم. از آنجا که هر وسیله نقلیه ای حرکت می کند، رنگ دارد، سرعت دارد، ترمز می گیرد و… می توانیم همه این متدها و فیلدها( کدام متدها و فیلدها!؟) را در کلاس وسیله نقلیه تعریف کنیم. حال یک وهله از این کلاس را در نظر بگیرید (مثلا دوچرخه!). یک دوچرخه یک وسیله نقلیه است که همه خصوصیات عمومی یک وسیله نقلیه را دارد و البته خصوصیاتی دارد که مختص خودش هستند و در انواع دیگر یافت نمی شوند. به این منظور این دوچرخه می تواند ویژگیها و متدهای مشترک را از کلاس وسیله نقلیه به ارث ببرد و در عین حال ویژگیهای منحصر به خود را نیز داشته باشد. قابلیت استفاده دوباره از کد (Reusability) یکی از مزیات اصلی ارث بری است.
Encapsulation
همانطور که از اسمش پیداست، به قرار دادن پیاده سازی در یک کپسول اشاره می کند، به طوری که کاربر بیرونی از نحوه پیاده سازی مطلع نباشد و فقط بداند که این کپسول کار خاصی را انجام می دهد. وقتی یک کپسول می خورید نمی دانید که در داخل آن چه چیزی هست و فقط به این فکر می کنید که این کپسول چه تاثیری در بدن شما می گذارد!
فرض کنید سوار ماشینی هستید که به سرعت در حرکت است! در مسیری که می روید ماشین پدر نامزدتان از روبرو به شما نزدیک می شود و سعی می کنید سریع ترمز بگیرید تا برخورد نکنید. اگر قرار باشد که بدانید بعد از فشار دادن پدال ترمز چه عملیاتی انجام می شود تا ترمز گرفته شود، دیگر باید از ازدواج قطع امید کنید. ولی اگر تنها بدانید که با فشار دادن پدال، ترمز گرفته می شود شما خوشبخت خواهید شد. در واقع ما در اینجا کار ترمز گرفتن ماشین را به صورت یک کپسول آماده در نظر می گیریم. هدف Encapsulation این است که ما را از پرداختن به ریز موضوعات رها کند و اشیاء را به صورت یک جعبه سیاهی بدانیم که به ازای یک ورودی خاص خروجی خاصی می دهند. اگر می خواهیم کدهای ما نیز این مورد را رعایت کنند باید سعی کنیم نگاه کپسولی به اشیاء و عملکرد آنها داشته باشیم. در #C برای کپسوله کردن از Access Modifierهای protected ،private و public استفاده می شود.
Polymorphism
فرض کنید پدر شما کار خاصی را به طریق خاصی انجام می دهد. مثلا برای پختن غذا (حقیقتی است تلخ!) اول ظرفهای دیشب را شسته و بعد گاز را روشن می کند و بعد غذا می پزد! شما که خصوصیات پدر و کارهای او را به ارث می برید برای مثال برای پختن غذا ابتدا گاز را روشن می کنید، بعد کبریت می کشید، غذا را می پزید و بعد ظرفهای دیشب را می شویید! (توصیه می کنم نگذارید ظرفهایتان نشسته بمانند!) برادر شما ممکن است همین کار را به طریق دیگری انجام دهد. پختن غذا کاری است که شما از پدر خود به ارث می برید!!! ولی آن را به طریق دیگری انجام می دهید. یعنی یک کار ثابت توسط فرزندان مختلف یک پدر به طرق مختلفی انجام می شود. این دقیقا همان چیزی است که به آن چند شکلی یا Polymorphism می گویند.
Abstraction
تجرید یا مجرد سازی! به کلاسی مجرد گفته می شود که پیاده سازی متدها در آن انجام نمی شود! بر خلاف انسانها که مجرد تعریف دیگری برایشان دارد! حال سئوالی پیش می آید که اگر کلاسی داشته باشیم که نخواهیم پیاده سازی متدها را در آن انجام بدیم، از آن کلاس چه استفاده ای می کنیم؟ برای پاسخ به این سئوال شرایط زیر را در نظر بگیرید:
فرض می کنیم که شما رییس یک شرکت بزرگ برنامه نویسی هستید و می خواهید پروژه بزرگی را انجام دهید. برای اجرای پروژه از برنامه نویسان مختلفی استفاده می کنید که ممکن است همه آنها هموطن نباشند! مثلا هندی، ایرانی یا آلمانی باشند! اگر قرار باشد هر برنامه نویسی در نامگذاری متدها و کلاسهایش آزاد باشد، در کد نویسی هرج و مرج به وجود می آید. شما به عنوان مدیر پروژه، کلاسی تعریف می کنید که در آن تمام متدها با ورودی و خروجی هایشان مشخص باشند. ولی این متدها را پیاده سازی نمی کنید و کار پیاده سازی را به برنامه نویسان می دهید و از آنها می خواهید که همه کلاسهایی را که می نویسند از این کلاس شما به ارث ببرند و متدها را به طور دلخواه پیاده سازی کنند. این باعث می شود که شما با داشتن یک کلاس، ورودی و خروجی های مد نظر خود را داشته باشید و دیگر نگران برنامه نویسان نباشید. کلاسی که شما تعریف می کنید یک کلاس مجرد نامیده می شود.
برای تعریف یک کلاس مجرد از کلمه کلیدی abstract استفاده می کنیم. فیلدهایی که می خواهیم در کلاسهای مشتق شده از این کلاس پیاده سازی شوند حتما باید با abstract تعریف شوند. یک کلاس مجرد می تواند فیلدها و متدهای نامجرد داشته باشد. اگر متد نامجردی در یک کلاس مجرد تعریف کردید، حتما باید آن را پیاده سازی کنید و نمی توانید پیاده سازی آن را به کلاسهای مشتق شده بسپارید.
Interface
اینترفیس در برنامه نویسی همانند همان کلاس است تنها با این تفاوت که هیچکدام از اعضای آن پیاده سازی نمی شوند. در واقع یک اینترفیس گروهی از متدها، خصوصیات، رویدادها و Indexer ها هستند که در کنار هم جمع شده اند. اینترفیس ها را نمی توان Instantiate (وهله سازی) کرد (یعنی نمی توان وهله ای از یک اینترفیس ایجاد کرد!). تنها چیزی که یک اینترفیس دارا می باشد امضای (signature) تمامی اعضای آن می باشد. به این معنی که ورودی و خروجی متدها، نوع Property ها و… در آن تعریف می شوند ولی چیزی پیاده سازی نمی شود. اینترفیس ها سازنده و فیلد ندارند (امری است بدیهی! چرا؟). یک اینترفیس نمی تواند Operator Overload داشته باشد و دلیل آن این است که در صورت وجود این ویژگی، احتمال بروز مشکلاتی از قبیل ناسازگاری با دیگر زبانهای NET. مانند VB.NET که از این قابلیت پشتیبانی نمی کند وجود داشت. نحوه تعریف اینترفیس بسیار شبیه تعریف کلاس است تنها با این تفاوت که در اینترفیس پیاده سازی وجود ندارد.
حالا این اینترفیس در کجا به کار می آید؟ اگر با C++کار کرده باشید ( در آن صورت کارتان خیلی درست می باشد!!!) با واژه ارث بری چند گانه آشنا هستید. ولی احتمالا شنیدید که جاوا و #C از ارث بری چندگانه پشتیبانی نمی کنند. (یعنی یک کلاس از چند کلاس دیگر به ارث ببرد). گاهی لازم داریم از چند کلاس به ارث ببریم. راه حلش این است که از اینترفیس ها استفاده کنیم. ولی بدانید که اگر از اینترفیسی به ارث بردید باید تمام متدهای آن را پیاده سازی کنید. یک کلاس می تواند از n تا اینترفیس و تنها یک کلاس به ارث ببرد.
نوشته منتظر
برگرفته از :
كد - لینک:
http://alem.ir
:104:
گردآونده:طه-Borna66__________________
در دنیایی واقعی . انسانها اشیا را کلاسه بندی می کنند و از این طریق بهتر پی به خصوصیات اشیا و وابستگی آنها میبرند . ذهن انسان به سمت ساختن یک ساختار درختی برای اشیا و رده بندی آنها و حفظ و نگهداری خصوصیات هر رده آموزش داده شده است .
برای مثال کلاس موجودات زنده به دو زیر کلاس بزرک گیاهان و جانوران تقسیم می شود . جانوران نیز خود به زیر کلاس های مهره داران و بی مهرگان تفکیک می گردند . پستانداران یکی از زیر کلاسهای کلاس مهره داران است . و انسان زیر کلاسی از پستان داران را تشکیل می ده . کلاس موجودات زنده دارای صفاتی است که این صفات در تمام آنها مشترک است . از این صفات می توان تنفس . تغذیه و رشد را نام برد . زیر کلاس جانوران علاوه بر صفات کلاس موجودات زنده صفات خاص خود را نیز دارند . از این صفات حرکت و تولید مثل را میتوان ذکر کرد . این روند برای زیر کلاسهای پایین تر می تواند ادامه پیدا کند .
اگر دید حاکم بر تحلیل و طراحی یک سیستم نرم افزاری به گونه ای باشد که سیستم را به عنوان یک کلاس ببیند که دارای توانایی انجام تعدادی فعالییت است و این فعالییت ها بر روی نوع داده ای انجام می شود . و سیستم به چند زیر سیستم تقسیم می شود و هر زیر سیستم مشابه سیستم اولیه متشکل از تعدادی فعالیت و تعدادی نوع دادهای باشد و این کار به قدر کافی ادامه پیدا کند . آنگاه تحلیل و طراحی از نوع شی گرا خواهد بود . پیاده سازی چنین طرحی نیاز به ابزار خاص خود دارد . برنامه سازی با به کار گیری این ابزار به صورت علمی و اصولی در پیاده سازی طرح مورد نظر . برنامه سازی شی گرا نامیده می شود . برای برنامه سازی شی گرا ابتدا باید با مفاهیم شی گرایی آشنایی کامل پیدا کرد . برای درک بهتر این مفهوم در مقدمه دو مفهوم کلاس و شی را به اختصار توضیح می دهیم .
کلاس
کلاس روشی برای بسته بندی نوع داده مجرد است . در کلاس امکان بسته بندی و محصور کردن (Encapsulation ) مجموعه ای از داده ها . روال های پردازش کننده این داده ها را به صورت یک بسته واحد فراهم می کند .
داده های داخل یک کلاس به وسیله کلاس محافظتمی گردد . به گونه ای که پردازش داده های خصوصی یک کلاس تنها از طریق روال های داخلی آن امکان پذیر است . داده های یک کلاس را متغیر های کلاس و روال های آن را روش نامیده اند . برای مثال . کلاس انسان ها یک کلاس قابل تعریف است . در این کلاس خصوصیات مشترک انسان ها تعریف می گردد و هیچ انسان خاصی را نشان نمی دهد . کلاس یک نوع است . همانگونه که مثلا int یک نوع است .
عملیات محاسباتی ( یا غیر محاسباتی ) بر روی نوع داده انجام نمی شود . بلکه این عملیات بر روی متغیرهایی که از این نوع داده تعریف می گردد انجام می شود . بطور مشابه عملیات محاسباتی ( یا غیر محاسباتی ) روی کلاس انجام نمی شود .
شیء
یک شی یک نمونه واقعی از یک کلاس است . همانگونه که در C (زبان غیر شی گرا ) می توان متغیر یا متغیر هایی از یک نوع مثلا int تعریف کرد و این متغیر هارا پردازش نمود . در یک زبان شی گرا میتوان شی یا اشیایی را از یک کلاس تعریف کرد . این اشیا موجودیت واقعی پیدا می کنند و قابل پردازش هستند . همانطور که یک انسان خاص . از کلاس انسانها موجودیت واقعی پیدا می کند و فعالیت می کند تغذیه می کند و… در چارچوب یک زبان شی گرا به متغیر های یک نوع داده نیز اشیا میگویند . هر شی داده مخصوص به خود دارد که متغیر های عضو یا داده های عضو نامیده می شوند .
تاریخچه
دیدگاه شیگرایی (Object Oriented) از اواسط دهه ۱۹۷۰ تا اواخر دهه ۱۹۸۰ در حال مطرح شدن بود. در این دوران تلاشهای زیادی برای ایجاد روشهای تحلیل و طراحی شیگرا صورت پذیرفت. در نتیجة این تلاشها بود که در طول ۵ سال یعنی ۱۹۸۹ تا ۱۹۹۴، تعداد متدولوژیهای شیگرا از کمتر از ۱۰ متدولوژی به بیش از ۵۰ متدولوژی رسید. تکثر متدولوژیها و زبانهای شیگرایی و رقابت بین اینها به حدی بود که این دوران به عنوان “جنگ متدولوژیها” لقب گرفت. از جمله متدولوژیهای پرکاربرد آن زمان میتوان از Booch، OOSE، OMT، Fusion، Coad-Yourdan، Shlayer-Mellor وغیره نام برد. فراوانی و اشباع متدولوژیها و روشهای شیگرایی و نیز نبودن یک زبان مدلسازی استاندارد، باعث مشکلات فراوانی شده بود. از یک طرف کاربران از متدولوژیهای موجود خسته شده بودند، زیرا مجبور بودند از میان روشهای مختلف شبیه به هم که تفاوت کمی در قدرت و قابلیت داشتند یکی را انتخاب کنند. بسیاری از این روشها، مفاهیم مشترک شیگرایی را در قالبهای مختلف بیان میکردند که این واگرایی و نبودن توافق میان این زبانها، کاربران تازهکار را از دنیای شیگرایی زده میکرد و آنها را از این حیطه دور میساخت. عدم وجود یک زبان استاندارد، برای فروشندگان محصولات نرمافزاری نیز مشکلات زیادی ایجاد کرده بود.
***
در این تحقیق شی گرایی را در دو زبان برنامه نویسی ( C++ و C# ) مورد بررسی قرار می دهم و شی گرایی و موارد آن را در هر یک به اختصار توضیح می دهم .
در ابتدا نگاهی می اندازیم به این خاصیت در زبان برنامه نویسی C++ و در ادامه شی گرایی را در زبان C# مورد بررسی قرار میدهیم وسپس لیست برخی از برنامه های شی گرا را ذکر می کنیم .
شی گرایی در زبان C++
برنامه نویسی شی گرا چیست ؟
از آنجایی که اساس تکوین c++ برنامه نویسی شی گرا است . پس مهم است که تعریف دقیقی را از برنامه نویسی شی گرا ارائه دهیم . شی گرا از بهترین مفاهیم برنامه سازی ساخت یافته بوجود آمده است و با چندین مفهوم قوی ترکیب شده که امکان سازماندهی برمانه ها به طور کارامد را فراهم می کند . به طور کلی هنگامی که در حالتی شی گرا نیز برنامه می نویسید مساله را به بخش های تشکیل دهنده آن تجزیه می کنید . هر مولفه ای یک شی خود ظرف می شود . که شامل دستور العملهای خودش و داده های مرتبط به آن شی است . از طریق این عملیات پیچیدگی کاهش یافته و می توان برنامه های بزرگ را مدیریت کرد . همه زبان های برنامه نویسی شی گرا در سه چیز مشترک هستند : کپسوله سازی . چند ریختی و وراثت . که در زیر اشاره مختصری به هر یک از آنها می کنیم .
کپسوله سازی
همانطوری که میدانید تمام برنامه ها از دو عنصور اصلی تشکیل می شوند : عبارت برنامه ( کد ) و داده ها . کد بخشی از برنامه است که عملیات را اجرا می کند و داده ها اطلاعاتی است که توسط این عملیات تحت تاثیر قرارگرفته . کپسوله سازی یک مکانیزم برنامه نویسی است که کد و داده را با هم در یک جا قرار داده و هر دو را از استفاده نادرست وتداخل خارجی ایمن نگه می دارد.
در یک زبان شی گرا . کد و داده ممکن است باهم در چنین روشی محدود شوند که یک جعبه سیاه خود ظرف را ایجاد می کند . درون جعبه تمام داده های مورد نیلز و کد است . هنگامی که در این روش کر و داده ها با هم پیوند برقرار می کنند . یک شی به وجود می آید . به عبارت دیگر . یک شی ابزاری است که از کپسوله سازی پشتیبانی می کند .
درون یک شی ( کد و داده ها ) یا هر دو ممکن است برای آن شی محلی ( خصوصی / private ) یا عمومی ( public ) باشند . کد یا داده های محلی فقط توسط بخش دیگری از شی شناخته شده و قابل دست یابی هستند .
به همین دلیل کد یا داده محلی برای قطعه ای از برنامه که خاج از شی است . قابل دسترس نمی باشد . هنگامی که کد یا داده ها عمومی هستند بخشهای دیگری از برنامه ممکن است به آنها دسترسی داشته باشند حتی اگر درون شی تعریف شده باشند بخش های عمومی یک شی برای ارائه یک ارتباط کنترل شده با عناصر محلی شی مورد استفاده قرار می گیرند .
چند ریختی
چند ریختی کمیتی است که به یک رابط امکان می دهد تا برای یک کلاس عمومی از عملیات مورد استفاده قرار گیرد . عمل خاص توسط ذات حقیقی شی تعیین می شود . یک مثال ساده از چند ریختی در فرمان اتومبیل است . فرمان اتومبیل برای تمام اتومبیل ها بدون توجه به مکانیزمی که مورد استفاده قرار می دهند یکسان است . فرممان برای اتومبیلی که به صورت دستی کار میکند یا با نیروی برق یا هر چیز دیگری عمل یکسانی را انجام میدهد . بنابراین بعد از اینکه شما چگونگی عمل کردن فرمان را یاد گرفتید میتوانید هر نوع اتومبیلی را برانید . همین هدف نیز می تواند در برنامه نویسی اعمال شود . به عنوان مثال یک پشته ( لیستی که در آن اولین ورودی آخرین خروجی است مثل تعدادی سکه که روی هم قرار می گیرند ) را در نظر بگیرید. ممکن است برنامهای داشته باشید که نیاز به سه نوع مختلف پشته داشته باشد یک پشته برای مقادیر اعداد صحیح . یک پشته برای اعداد اعشاری و یک پشته برای کاراکترها مورد استفاده قرار گیرد . در این صورت الگوریتمی که هر سه پشته را پیاده می کند یکسان است حتی اگر داده هایی که در آنها ذخیره می شود متفاوت باشند . در یک زبان غیر شی گرا نیاز خواهید داشت تا سه نوع مختلف از روال ها ی پشته را ایجاد کرده . به هر کدام نام متفاوتی قرار داده و برای هر کدام از روابط خاص خودش استفاده کنید . به دلیل وجود چند ریختی در C++ می توانید یک مجموعه روال عمومی از پشته ایجاد کرده و آن را برای هر سه نوع به کار ببرید . با این روش بعد از اینکه استفاده از یک پشته را یاد گرفتید می توانید همه انواع آن را به کار ببرید .
به طور کلی مفهوم چند ریختی اغلب توسط عبارت ” یک رابط. چندین روش ” بیان می شود . این بدین معنی است که امکان طراحی یک رابط عمومی برای گروهی از عملیات مرتبط وجود دارد .
چند ریختی با اعمال رابط یکسانی که برای تعیین یک کلاس عمومی مورد استفاده قرار می گیرد . به کاهش پیچیدگی کمک می کند . این است وظیفه کامپایلر تا فعالیت خاصی ( مثل متد ) را برای اعمال روی آن انتخاب کند . شما به عنوان برنامه نویس نیاز ندارید تا این انتخاب را انجام دهید شما فقط نیاز دارید رابط عمومی را به خاطر سپرده و استفاده کنید .
زبان های برنامه نویسی شی گرای اولیه چون به صورت مفسری بودند از چند ریختی در زمان اجرا پشتیبانی می کردند . ولی چون C++ کامپایلری است پس هم در زمان اجرا و هم زمان کامپایل از چند ریختی پشتیبانی می کند.
وراثت
وراثت . عملی است که یک شی می تواند مشخصه های شی دیگری را بدست آورد . به همین دلیل از مفهوم دسته بندی سلسله مراتبی پشتیبانی می کند . اگر در رابطه با وراثت بیشتر فکر کنید اطلاعات بیشتری راجع به دسته بندی سلسله مراتبی ( از بالا به پایین ) بدست خواهید آورد . به عنوان مثال سیب قرمز بخشی از دسته بندی سیب که آن هم بخشی از کلاس میوه هاست که آن هم در کلاس بزرگتری به نام غذا قرار دارد . کلاس غذا دارای مشخصات اصلی ( خوراکی . پروتئین و غیره ) است که به طور منطقی به زیر کلاس های غذا اعمال می شود . علاوی بر این مشخصات کلاس میوه دارای مشخصه های ( آبدار. شیرین و غیره ) است که آن را از سایر غذا ها متمایز می کند . کلاس سیب نیز مشخصه های خاصی را برای یک سیب تعریف می کند که عبارتند از : رسیدن روی درخت و غیره . یک سیب قرمز تمام خصوصیات کلاسهای بالاتر را به ارث می برد و فقط مشخصه هایی که منحصر به فرد هستند را تعریف خواهیم کرد .
بدون استفاده از وراثت هرشی به طور مجزا بایستی تمام مشخصه های خودش
را تعریف کند .با استفاده از وراثت شی فقط نیاز به تعریف مشخصه هایی دارد که در داخل آن کلاس منحصر به فرد هستند . این سبب می شود که صفات عمومی را از پدرشان به ارث ببرند .
بنابراین . مکانیزم وراثت به یک شی امکان میدهد تا نمونه خاصا از یک حالت عمومی تر باشد .
C++ برنامه نویسی شی گرا را پیاده سازی می کند .
چندین ویژگی در C++ وجود دارد که از کپسوله سازی . چند ریختی و وراثت پشتیبانی می کنند. به خاطر داشته باشید که می توانید از C++ برای نوشتن هر نوع برنامه ای و با استفاده از هر نوع روشی استفاده کنید . این مطلب کهC++ از OOP پشتیبانی می کند بدین معنی نیست که فقط می توانید برنامه های شی گرا بنویسید . همانند پیشینه خود ( یعنیc ) یکی از قویترین مزایای C++ قابلیت انعطاف آن است .
شی گرایی در زبان C#
شئ گرایی (OOP) در #C بر چند پایه استوار است که به قرار زیرند:
- Inheritance
- Encapsulation
- Polymorphism
- Abstraction
- Interface
اکنون به توضیح مختصر هر یک می پردازیم.
Inheritance ارث بری
پدر و فرزندی را در نظر بگیرید. هر پدری مشخصات فردی به خصوصی دارد. فرزند وی می تواند همه خصوصیات او را به ارث برد و خصوصیتهای دیگری نیز داشته باشد که پدرش ندارد. این یعنی ارث بری! برای مثال پدر وقتی عصبانی می شود، داد و فریاد می کند. پسر هم این خصوصیت را به ارث می برد با این تفاوت که وقتی عصبانی می شود، علاوه بر داد زدن، چند عدد بشقاب هم می شکند. در برنامه نویسی شئ گرا از مفهوم ارث بری استفاده های زیادی می شود. برای تفهیم راحت تر مسئله فرض کنید کلاسی به نام وسیله نقلیه داریم. از آنجا که هر وسیله نقلیه ای حرکت می کند، رنگ دارد، سرعت دارد، ترمز می گیرد و… می توانیم همه این متدها و فیلدها( کدام متدها و فیلدها!؟) را در کلاس وسیله نقلیه تعریف کنیم. حال یک وهله از این کلاس را در نظر بگیرید (مثلا دوچرخه!). یک دوچرخه یک وسیله نقلیه است که همه خصوصیات عمومی یک وسیله نقلیه را دارد و البته خصوصیاتی دارد که مختص خودش هستند و در انواع دیگر یافت نمی شوند. به این منظور این دوچرخه می تواند ویژگیها و متدهای مشترک را از کلاس وسیله نقلیه به ارث ببرد و در عین حال ویژگیهای منحصر به خود را نیز داشته باشد. قابلیت استفاده دوباره از کد (Reusability) یکی از مزیات اصلی ارث بری است.
Encapsulation
همانطور که از اسمش پیداست، به قرار دادن پیاده سازی در یک کپسول اشاره می کند، به طوری که کاربر بیرونی از نحوه پیاده سازی مطلع نباشد و فقط بداند که این کپسول کار خاصی را انجام می دهد. وقتی یک کپسول می خورید نمی دانید که در داخل آن چه چیزی هست و فقط به این فکر می کنید که این کپسول چه تاثیری در بدن شما می گذارد!
فرض کنید سوار ماشینی هستید که به سرعت در حرکت است! در مسیری که می روید ماشین پدر نامزدتان از روبرو به شما نزدیک می شود و سعی می کنید سریع ترمز بگیرید تا برخورد نکنید. اگر قرار باشد که بدانید بعد از فشار دادن پدال ترمز چه عملیاتی انجام می شود تا ترمز گرفته شود، دیگر باید از ازدواج قطع امید کنید. ولی اگر تنها بدانید که با فشار دادن پدال، ترمز گرفته می شود شما خوشبخت خواهید شد. در واقع ما در اینجا کار ترمز گرفتن ماشین را به صورت یک کپسول آماده در نظر می گیریم. هدف Encapsulation این است که ما را از پرداختن به ریز موضوعات رها کند و اشیاء را به صورت یک جعبه سیاهی بدانیم که به ازای یک ورودی خاص خروجی خاصی می دهند. اگر می خواهیم کدهای ما نیز این مورد را رعایت کنند باید سعی کنیم نگاه کپسولی به اشیاء و عملکرد آنها داشته باشیم. در #C برای کپسوله کردن از Access Modifierهای protected ،private و public استفاده می شود.
Polymorphism
فرض کنید پدر شما کار خاصی را به طریق خاصی انجام می دهد. مثلا برای پختن غذا (حقیقتی است تلخ!) اول ظرفهای دیشب را شسته و بعد گاز را روشن می کند و بعد غذا می پزد! شما که خصوصیات پدر و کارهای او را به ارث می برید برای مثال برای پختن غذا ابتدا گاز را روشن می کنید، بعد کبریت می کشید، غذا را می پزید و بعد ظرفهای دیشب را می شویید! (توصیه می کنم نگذارید ظرفهایتان نشسته بمانند!) برادر شما ممکن است همین کار را به طریق دیگری انجام دهد. پختن غذا کاری است که شما از پدر خود به ارث می برید!!! ولی آن را به طریق دیگری انجام می دهید. یعنی یک کار ثابت توسط فرزندان مختلف یک پدر به طرق مختلفی انجام می شود. این دقیقا همان چیزی است که به آن چند شکلی یا Polymorphism می گویند.
Abstraction
تجرید یا مجرد سازی! به کلاسی مجرد گفته می شود که پیاده سازی متدها در آن انجام نمی شود! بر خلاف انسانها که مجرد تعریف دیگری برایشان دارد! حال سئوالی پیش می آید که اگر کلاسی داشته باشیم که نخواهیم پیاده سازی متدها را در آن انجام بدیم، از آن کلاس چه استفاده ای می کنیم؟ برای پاسخ به این سئوال شرایط زیر را در نظر بگیرید:
فرض می کنیم که شما رییس یک شرکت بزرگ برنامه نویسی هستید و می خواهید پروژه بزرگی را انجام دهید. برای اجرای پروژه از برنامه نویسان مختلفی استفاده می کنید که ممکن است همه آنها هموطن نباشند! مثلا هندی، ایرانی یا آلمانی باشند! اگر قرار باشد هر برنامه نویسی در نامگذاری متدها و کلاسهایش آزاد باشد، در کد نویسی هرج و مرج به وجود می آید. شما به عنوان مدیر پروژه، کلاسی تعریف می کنید که در آن تمام متدها با ورودی و خروجی هایشان مشخص باشند. ولی این متدها را پیاده سازی نمی کنید و کار پیاده سازی را به برنامه نویسان می دهید و از آنها می خواهید که همه کلاسهایی را که می نویسند از این کلاس شما به ارث ببرند و متدها را به طور دلخواه پیاده سازی کنند. این باعث می شود که شما با داشتن یک کلاس، ورودی و خروجی های مد نظر خود را داشته باشید و دیگر نگران برنامه نویسان نباشید. کلاسی که شما تعریف می کنید یک کلاس مجرد نامیده می شود.
برای تعریف یک کلاس مجرد از کلمه کلیدی abstract استفاده می کنیم. فیلدهایی که می خواهیم در کلاسهای مشتق شده از این کلاس پیاده سازی شوند حتما باید با abstract تعریف شوند. یک کلاس مجرد می تواند فیلدها و متدهای نامجرد داشته باشد. اگر متد نامجردی در یک کلاس مجرد تعریف کردید، حتما باید آن را پیاده سازی کنید و نمی توانید پیاده سازی آن را به کلاسهای مشتق شده بسپارید.
Interface
اینترفیس در برنامه نویسی همانند همان کلاس است تنها با این تفاوت که هیچکدام از اعضای آن پیاده سازی نمی شوند. در واقع یک اینترفیس گروهی از متدها، خصوصیات، رویدادها و Indexer ها هستند که در کنار هم جمع شده اند. اینترفیس ها را نمی توان Instantiate (وهله سازی) کرد (یعنی نمی توان وهله ای از یک اینترفیس ایجاد کرد!). تنها چیزی که یک اینترفیس دارا می باشد امضای (signature) تمامی اعضای آن می باشد. به این معنی که ورودی و خروجی متدها، نوع Property ها و… در آن تعریف می شوند ولی چیزی پیاده سازی نمی شود. اینترفیس ها سازنده و فیلد ندارند (امری است بدیهی! چرا؟). یک اینترفیس نمی تواند Operator Overload داشته باشد و دلیل آن این است که در صورت وجود این ویژگی، احتمال بروز مشکلاتی از قبیل ناسازگاری با دیگر زبانهای NET. مانند VB.NET که از این قابلیت پشتیبانی نمی کند وجود داشت. نحوه تعریف اینترفیس بسیار شبیه تعریف کلاس است تنها با این تفاوت که در اینترفیس پیاده سازی وجود ندارد.
حالا این اینترفیس در کجا به کار می آید؟ اگر با C++کار کرده باشید ( در آن صورت کارتان خیلی درست می باشد!!!) با واژه ارث بری چند گانه آشنا هستید. ولی احتمالا شنیدید که جاوا و #C از ارث بری چندگانه پشتیبانی نمی کنند. (یعنی یک کلاس از چند کلاس دیگر به ارث ببرد). گاهی لازم داریم از چند کلاس به ارث ببریم. راه حلش این است که از اینترفیس ها استفاده کنیم. ولی بدانید که اگر از اینترفیسی به ارث بردید باید تمام متدهای آن را پیاده سازی کنید. یک کلاس می تواند از n تا اینترفیس و تنها یک کلاس به ارث ببرد.
نوشته منتظر
برگرفته از :
كد - لینک:
http://alem.ir
:104:
گردآونده:طه-Borna66__________________