اصلا چرا باید درگیر مفهومی مثل شی گرایی یا OOP بشیم ؟ این پارادایم توسعه داده شد تا ما راحتتر بتونیم کد ها رو دسته بندی کنیم ، نگهداری کنیم و حتی بهتر از همه اینا ، با این پارادایم کد های ما خیلی منعطف تر میشن
قبل از اینکه با این پارادایم آشناشیم همیشه کدها در هم و برهم بود،احتمالا برای اینکه یه کارو انجام بدیم چهار بار یک تیکه کدو تکرار میکردیم و تازه بدتر ازهمه این بود که اگر میخواستیم بریم سراغ یه پروژه دیگه احتمالا هیچ کدوم از دستوراتی که توی کد قبلی زده بودیم بدردمون نمیخورد و باید از اول شروع میکردیم به نوشتن چون انقدر همه چیز در هم و برهم بود که احتمالا اگر بعد یک ماه میرفتیم سراغش هیچی ازش نمیفهمیدیم ، انگار یه ظرف ماکارونی جلومونه که هرچند که خوشمزس ولی معلوم نیست چی توشه اصلا واسه همین اون مدل کد زدن معروف شد به Spaghetti code
اما لب کلام OOP چیه؟ یه راهی جلوپامون میذاره که یک سری شی object رو از کدمون بسازیم . اما چطوری؟ قبلا از کلاس استفاده میکردیم.کلاس چیه؟کلاس نقشست ، اون اشیایی که قراره بسازیم یه ساختار دارن قاعده و قانون دارن مثلا شرایطوقوانینی که تو تولید شیر کاکائو وجود داره تو تولید نوشابه وجود نداره حالا هی بیایم به این خط تولید(کدمون) بگیم شیرکاکائو(شی) بساز ولی دستور ساخت(کلاس) نوشابه رو بهش بدیم!!!
هرچند این قوانین مفهومی و انتزاعی باشن اما همونطور که گفتم اصل و اساس ایجاد آبجکت ها تو دنیای واقعی هستند، نقشه ای که برای ساختن خونه طراحی میشه هم یک کلاسه و خونه هایی که تو دنیای واقعی بر اساس اون نقشه درست میشن هم شی هستند. اما این اشیایی که از کلاس ها ایجاد میشن یک اسم دیگه هم دارن و معروفند به نمونه یا instance. ما میتونیم هزاران instance متفاوت داشته باشیم که از یک کلاس دارن استفاده میکنن مثل کلاس ماشین که یک نمونش میشه بنز یک نمونش هم میشه پراید(!!!) هردوشون وسیله نقلیه هستند اما(این کجا و آن کجا) تفاوت های فاحشی هم باهم دارن ولی خب با توجه به تفاوت هاشون هردو چهارتا چرخ دارن، یک فرمون، موتور و ...
پس چطور باید این کلاس ها رو طراحی کنیم؟چطور باید مسایل دنیای واقعی رو توی کلاس ها پیاده سازی کنیم؟
بصورت کلی 4 تا قاعده اساسی توی شی گرایی وجود دارن که میتونن به ما کمک کنن که یک کلاس رو به خوبی بتونیم پیاده سازی کنیم :
1)انتزاع یا abstraction: یعنی ساده سازی، یعنی یک سری فرآیند هایی که دستو پا گیرن رو از جلوی دستو پا برداریم مثلا چی؟مثلا ما میخوایم یه صفحه نمایش داشته باشیم اگر از انتزاع استفاده نکنیم باید برای هر عملی که توی یک صفحه نمایش اتفاق میفته یک دکمه برای کاربر اضافه کنیم مثلا تنظیم نور،دکمه خاموش و روشن کردن صفحه،میزان سردی و گرمی رنگ ها ، دمای صفحه نمایش چقدر شده ، پورت ورودیش چندتا خالی مونده ، و هزاران مسایل مربوط به داخل و خارج اون صفحه نمایش که اصلا در حالت عادی یک کاربر نیازی نداره بدونه در دنیای واقعی تمام این فعالیت ها ازدید کاربر پنهان شدن و کاربر فقط با دکمه روشن و خاموش کردن صفحه نمایش کار داره و بقیه موارد نه اینکه بدرد نخور باشند، فقط دم دست کاربر نیستن
2) کپسوله سازی encapsulation: یعنی بیایم قسمت های مختلف یک کلاس رو خصوصی کنیم که از بیرون از کلاس به اون بخش ها دسترسی نداشته باشیم به مثال بالا دقت کنیم یک بار دیگه ، صفحه نمایش ما قابلیت اندازه گیری دمای داخل خودش رو داره بنابراین یک متد و فرآیندی برای این قضیه داخل این صفحه نمایش فعاله ولی آیا این فرآیند باید از خارج از صفحه نمایش بشه کنترلش کرد ؟ قطعا پاسخ نه خواهد بود.
3)ارث بری inheritance: برای این مورد بیاین مثال رو به یک مثال واضح تر تبدیل کنیم، درنظربگیرید که ما موجودیتی به اسم یوزر توی برناممون داریم همچنین به جز اون موجودیتی به عنوان ادمین هم داریم خب قاعدتا بدون شک ، موجودیت ادمین موارد مشترک زیادی با یوزر داره مثل نام کاربری پسورد و...
user{ username password email login(password){ // some code } makeCall(){ // some code } }
================================================== admin{ username password email permissions login(password , Auth){ // some code } makeCall(){ // some code } runningSessions(user){ //some code } }
توی oop وقتی دو تا کلاس داریم که خیلی شبیه به همدیگه هستن و پراپرتی های یکسان دارن از ارث بری استفاده میکنیم توی این حالت یک کلاس والد parent و یک کلاس فرزند یا child داریم کلاس فرزند از والد ارث میبره، توی مثال ما {}()username password email login(password){ } makeCall تماما از یوزر به ادمین به ارث رسیدن
4)چندریختی polymorphism: وقتی میگیم چندریختی منظورمون دقیقا همون چندتا شکل وقیافه داشتنه این قابلیت کمکی که میتونه بهمون کنه اینه که میتونه متد هایی که از والدش به ارث برده رو بازنویسی (overwrite)کنه مثلا موجودیت ادمین برای لاگین شدن به کد دو عاملی هم نیاز داره و برخلاف والدش که تنها یک پارامتر password رو برای متد لاگین نیازداشت {}(login(password، توی ادمین میبینیم که پارامتر auth هم اضافه شده{}login(password , Auth).