برنامه نویسی شئ گرا (OOP)

oop

برنامه های امروزی، برنامه های پیچیده ای هستند که اطلاعات را به صورت گرافیکی به کاربران نشان می دهند. برنامه ها در پشت پرده از روابط پیچیده ای همچون روابط مابین مشتری ها، کالاها و سفارش ها تشکیل شده اند. برای مدیریت این پیچیدگی عظیم، تکنیکی به نام برنامه نویسی شئ گرا توسعه داده شد. که در آن با مدل کردن جنبه های ضروری سیستم، از پیچیدگی سیستم کاسته می شود. برنامه نویسی شئ گرا یا Object Oriented Programming که به اختصار OOP شناخته می شود، روشی نوین برای توسعه ی برنامه هاست.

تا قبل از ظهور برنامه نویسی شئ گرا، برنامه ها به شکل Procedural یا رویه ای نوشته می شدند. برنامه نویسی رویه ای مشکلات زیادی به همراه داشت که در ادامه به صورت خلاصه تعدادی از آنها را ذکر می کنیم:

  • در برنامه نویسی رویه ای، برنامه ها به توابع تقسیم می شدند.
  • با بزرگ شدن نرم‌افزار، برنامه نویسان مجبور به تکرار کدها می شدند.
  • توابع به صورت نامرتب و تو در تو یکدیگر را صـدا می زدند، و با تغییر در یک قسمت برنامه، برنامه نویس مجبور به تغییر کدها در قسمت های دیگر برنامه می شد.
  • برنامه ها در برنامه نویسی رویه ای تبدیل به کد اسپاگتی می شدند.

کد اسپاگتی

کد اسپاگتی، به کدی اطلاق می شود که در آن توابع و قطعات کد به هم وابسته و چسبیده اند و ایجاد تغییر در یک تابع باعث به هم ریختن سایر قسمت های برنامه می شود. در شکل زیر یک نمونه کد اسپاگتی آورده شده است.

spaghetticode

هدف برنامه نویسی شئ گرا

هدف از برنامه نویسی شئ گرا، افزایش قابلیت توسعه پذیری سیـستم و کارآمد شدن آنهاست. همچنین نگهداری و تغییر کد ها نیز آسانتر می شود.

مدل سازی

مدل ها برای مدیریت پیچیدگی و کمک به فهم مسائل برای حل آنها ایجاد می شوند. برای مثال نقشه ها مدل هایی از جاده ها هستند. گوی ها مدل هایی از زمین هستند. در اصل مدل ها نوعی ساده سازی به شمار می آیند.

earthsphere

کلاس ها و اشیاء

دنیا ترکیبی از اشیاء است. این اشیاء از یکدیگر متمایز هستند. انسان بدون آنکه متوجه شود خیلی از این اشیاء را در گروه هایی دسته بندی می کند. برای مثال فرض کنید که دو مداد رنگی به رنگ های قرمز و سبز دارید. هر دو مداد رنگی جزء دسته ی مدادرنگی هستند. یعنی مداد رنگی های قرمز و سبز نمونه ای از دسته بندی مداد رنگی هستند. پس می توان گفت مداد رنگی های قرمز و سبز هر کدام یک شیء یا Object هستند و گروه مدادرنگی یک Class است. هر Object نمونه ای از یک Class است.

در OOP ، توابـع و متـغیر های مرتبط در واحد هایی به اسم Class تجمـیع می شوند. در ادامه به معرفی تک تک مفاهـیم شئ گرایی می پردازیم.

مفاهیم شئ گرایی

در شئ گرایی با چهار مفهوم اصلی سروکار داریم:

  • Object
  • Property
  • Method
  • Class

Object

یک نمونه از کلاس است که دارای هویت بوده و قادر به بروز رفتار و ثبت حالت است. و موجودیت ها به صورت شئ یا object تعریف می شوند. برای مثال یک آهو نمونه ای از دسته بندی حیوانات (کلاس حیوان) است که گونه ای منحصر به فرد است و قادر به بروز رفتار است.

example of object

Property یا Attribute

هر شئ یک سری خصوصیات دارد که به آن صفت می گویند. به عنوان مثال هر مداد رنگی دارای خصوصیاتی نظیر رنگ، طول، قطر و … است.

example of property

Method

 هر شئ یک سری رفتار دارد که به آن متد می گویند. به عنوان مثال، در کلاسی که مربوط به تعامل با دیتابیس است رفتار هایی نظیر Delete, Update, Create و … را Method می گویند.

example of method

Class

 به مجموعه ای از اشیاء که دارای ویژگی و رفتار مشترک باشند کلاس می گویند. یک کلاس نمونه اولیه ای است که هر Object از روی آن ساخته می شود و دارای تعداد مشخصی فیلد، صفت، رویداد و متد است. کلاس یک نقشه کامل از یک شی مشخص است. کلاس ها می توانند ویژگی ها و توابع یکدیگر را به ارث ببرند. اشیاء از روی این کلاس ها ساخته می شوند. اشیاء صاحب Method ها  و Attribute های آن کلاس ها می شوند.

example of class

برای مثال اتومبیل یک کلاس است که می تواند شامل خصوصیات معینی مانند سرعت، رنگ و شکل باشد. هر اتومبیل یک شی از کلاس اتومبیل است که دارای سرعت، رنگ و شکل است. شرکت خودروسازی با ساخت یک اتومبیل در واقع شئ ای از روی کلاس اتومبیل ساخته است.

تا اینجا مفاهیم شئ گرایی توضیح داده شد. بهتر است مثالی بزنیم تا تمام این مفاهیم را با هم در دنیای واقعی ببینیم. به تصویر زیر دقت کنید:

example of oop

در شکل بالا، کلاسی به نام Human وجود دارد که دارای Attribute ها و Method هایی است. نمونه ای از روی این کلاس ساخته می شود که به عنوان مثال نامش اصغر، سنش 64 سال و ایمیلش asghar@mail.com است. همچنین متد Walk باعث می شود که اصغر راه برود و متد Talk باعث سخن گفتن اصغر می شود.

تعریف کلاس در #C

کلاس در #C با کلمه ی کلیدی Class شناخته می شود. و بدنه ی کلاس داخل {} قرار می گیرد. در بدنه ی کلاس Method ها و Attribute ها قرار می گیرند. در مثال زیر کد کلاس اتومبیل با متغیری به نام رنگ را می بینید.

در مثال زیر، خط اول طریقه ی ساخت یک Object از روی کلاس را نشان می دهد. و در خط بعد می خواهد مقدار attribute ای به نام Color از Object ساخته شده را در خروجی چاپ کند.

خروجی به شکل زیر خواهد بود:

red

در مثال زیر، کد کلاس با دو متغیر و یک متد آورده شده است.

Constructor یا سازنده ی کلاس

کلاس ها می توانند دارای  Constructor (متد سازنده) باشند. سازنده متدی است که در هنگام  ساخت یک نمونه شئ از یک کلاس، اجرا می شود. متد سازنده باید همنام کلاس باشد. مثال زیر کلاسی را نشان می دهد که Constructor دارد:

اگر دقت کنید در کلاس Car متدی به نام Car وجود دارد، پس آن متد، متد Constructor است. یکی از مزایای استفاده از Constructor خلاصه تر شدن کد هاست. به مثالهای زیر توجه کنید، اولین مثال، چگونگی استفاده از کلاس بدون Constructor را نشان می دهد و دومین مثال استفاده از کلاس با Constructor را نشان می دهد. .

مثال اول استفاده از کلاس بدون Constructor

مثال دوم استفاده از کلاس با Constructor

همانطور که پیداست استفاده از کلاسی که Constructor دارد به مراتب بهینه تر و خلاصه تر از کلاس ساده است.

ارکان چهارگانه برنامه نویسی شئ گرا

  1. Abstraction (انتزاع)

Abstract Class 

تمرکز بر نمایش موجودیت های ضروری دارد و نه تمام موجودیت ها. انتزاع می تواند با Abstract Class و یا Interface حاصل شود. به عنوان مثال برای روشن کردن تلویزیون تنها کافی ست که دکمه ی On روی ریموت کنترل را فشار دهیم. نیازی نیست که بدانیم امواج Infrared دقیقا چه کاری را انجام می دهند تا تلویزیون روشن شود.

کلاس Abstract همانند کلاس معمولی است با این سه تفاوت:

  • با کلمه ی کلیدی Abstract قبل از واژه ی Class شناخته می شود.
  • متد هایش می توانند بدنه داشته یا نداشته باشند. متد هایی که بدنه ندارند با عبارت کلیدی Abstract قبل از نام متد شناخته می شوند.
  • نمی توان از روی آنها نمونه ساخت.

مثال زیر یک کلاس Abstract را نشان می دهد که دو متد دارد، یکی با بدنه و دیگری بدون بدنه

همانطور که اشاره شد نمی توان از روی آن نمونه ساخت.در عوض می توان از آن ارث بری کرد. (در مورد وراثت بعدا توضیح داده خواهد شد.)

قطعه کد زیر نحوه ی استفاده از کلاس مشتق شده از کلاس Abstract را نشان می دهد.

اما انتزاع چه کاربردی دارد؟ با وجود کلاس معمولی چه نیازی به استفاده از کلاس Abstract وجود دارد؟ در اینجا ذکر یک مثال واقعی به درک مسئله کمک می کند. فرض کنید که افراد های درون یک دانشگاه به سه دسته تقسیم می شوند. دانشجویان، اساتید و کارمندان. این سه دسته بندی را می توان سه کلاس در نظر گرفت که خود از کلاس والدی به نام کلاس انسان ساخته شده اند. به عبارت دیگر سه دسته بندی وجود دارد. انسان هایی که دانشجو هستند، انسان هایی که استاد هستند و انسان هایی که کارمند هستند. یک فرد در دانشگاه نمی تواند فقط انسان باشد، حتما باید جزء یکی از این دسته بندی ها باشد. پس نیازی به ساخت یک نمونه از کلاس انسان نیست. در اینجا بهتر است که کلاس انسان از جنس Abstract Class باشد. (چون تنها تمرکز بر اطلاعات ضروری دارد و نه تمام اطلاعات)

Interface

راه دیگری برای رسیدن به Abstraction وجود دارد و آن اینترفیس است. اینترفیس همان Abstract Class است با این تفاوت که متدهایش بدنه ندارند و پیاده سازی نشده اند در عوض پیاده سازی آن متد ها به کلاسی واگذار می شود که آن اینترفیس را پیاده سازی می کند.

طبق قرارداد، ابتدای نام اینترفیس با حرف I شروع می شود. کلاسی که اینترفیس را پیاده سازی می کند باید تمام متد هایش را نیز پیاده سازی کند. بر خلاف کلاس، تمام اعضاء اینترفیس به صورت پیش فرض Public هستند. یکی از کاربرد های اینترفیس برای زمانی است که می خواهیم کلاینت را ملزم به پیاده سازی متد های معینی کنیم.

در مثال زیر اینترفیس IAnimal آورده شده است.

با دو نقطه می توان تعیین کرد که یک کلاس، کدام اینترفیس را پیاده سازی کند:

در C# یکی دیگر از تفاوت های اینترفیس با کلاس در این است که تنها از یک کلاس می توان ارث بری کرد ولی همزمان می توان چندین اینترفیس را پیاده سازی کرد.

2. Encapsulation (کپسوله سازی)

با محصور کردن دیتا و متدها در یک بسته منطقی، از دسترسی به جزئیات پیاده سازی جلوگیری به عمل می آورد. با استفاده از Access Modifiers یا سطوح دسترسی، کپسوله سازی حاصل می شود. به سطح مشخصی از مجوز برای دسترسی به خصوصیات و متد ها، سطوح دسترسی می گویند. انواع سطوح دسترسی:

  • Public

متد ها و صفات در تمام کلاس ها قابل دسترسی هستند. کد زیر نشان می دهد که در داخل کلاس Program می توان به صفت Model کلاس Car دسترسی داشت چون به صورت Public تعریف شده است.

  • Private

متد ها و صفات فقط در کلاسی که در آن تعریف می شوند قابل دسترسی هستند. شایان ذکر است که تمام اعضاء یک کلاس به صورت پیش فرض Private هستند. به مثال زیر دقت کنید.

این کد با خطا مواجه می شود. چون صفت Model در کلاس Car به صورت Private تعریف شده است و در کلاس های دیگر امکان استفاده از آن وجود ندارد.

  • Protected

متدها و صفات فقط در کلاسی که در آن تعریف می شوند و کلاسی که از آنها مشتق می شود قابل دسترسی هستند.

  • Internal

متدها و صفات در تمام کلاس های داخل یک فضای نام یا Assembly قابل دسترسی هستند.

  • Protected Internal

ترکیبی از protected و internal است. متدها و صفات تنها در همان اسمبلی یا فضای نام قابل دسترسی هستند و همزمان محدود به خود آن کلاس و کلاس های مشتق شده از آن هستند.

3. Inheritance (وراثت)

کلاس ها می توانند صفات و متد های یکدیگر را به ارث ببرند. این ویژگی می تواند به کاهش زمان توسعه و بهینه تر شدن سیستم کمک کند. به کد زیر دقت کنید، کلاس Car از کلاس Vehicle مشتق شده است یعنی صفات و متدهای آن را به ارث برده است.

4. Polymorphism (چندریختی)

یک کلاس می تواند چندین ریخت و شکل داشته باشد. در لغت کلمه ی Polymorphism خود از دو کلمه ی یونانی تشکیل شده است، Poly به معنای چند و Morph به معنای شکل و شمایل است. و در شئ گرایی به آن معناست که یک کلاس باید بتواند چندین شکل داشته باشد. مثال دانشگاه را به یاد دارید؟ این بار فرض کنید متدی به نام کارکردن در کلاس انسان وجود دارد، کلاس های دانشجویان، استاتید و کارمندان هر کدام از کلاس انسان مشتق شده اند اما هر کدام متد کارکردن را به شیوه ی خودشان پیاده کرده اند.

در ادامه دو مثال زده خواهد شد که در یکی Polymorphism وجود دارد و در دیگری وجود ندارد. مثال اول بدون Polymorphism است.

کلاس Dog از کلاس Animal مشتق شده است. در کلاس Animal یک متد به نام AnimalSound وجود دارد که متنی را در خروجی چاپ می کند. کلاس مشتق شده همان متد را دوباره تعریف می کند و می خواهد به شیوه ی خودش آن را پیاده سازی کند.

نحوه ی استفاده از آن:

اما در کمال تعجب می بینیم که با فراخوانی متد کلاس فرزند، متد کلاس پدر اجرا شده است.

The animal makes a sound

The animal makes a sound

چرا؟ در مثال زیر با استفاده از Polymorphism این مشکل را حل می کنیم. تنها کافی است که متدی را که می دانیم کلاس فرزند قرار است آن را جور دیگری پیاده سازی کند به صورت Virtual تعریف کنیم و در کلاس فرزند آن متد را به صورت Override تعریف کنیم. به مثال زیر دقت کنید:

نحوه ی استفاده از آن همانند مثال قبل است و با اجرای برنامه، خروجی زیر به نمایش درخواهد آمد:

The animal makes a sound

The dog says: bow wow

نوشته شده توسط mrbitmap علیرضا علی رمضانی

مقالات مرتبط

جدیدترین مقالات

فهرست