سلام! امروز نگاهی دقیق تر به اصل دیگری از برنامه نویسی شی گرا (OOP) - وراثت خواهیم انداخت. در همان زمان، ما انواع دیگر روابط بین کلاس ها - ترکیب و تجمع را مطالعه خواهیم کرد. این موضوع دشوار نخواهد بود: شما قبلاً بارها در سخنرانی های قبلی با ارث و نمونه های آن مواجه شده اید. امروز مهمترین چیز این است که دانش خود را تثبیت کنید، به مکانیسم وراثت نگاهی دقیق بیندازید و یک بار دیگر نمونه ها را مرور کنید :) بنابراین، بیایید برویم!
وراثت در جاوا و مزایای آن
همانطور که احتمالاً به خاطر دارید، وراثت مکانیزمی است که به شما امکان می دهد یک کلاس جدید را بر اساس کلاس موجود (والد) توصیف کنید. در این حالت، ویژگی ها و عملکرد کلاس والد توسط کلاس جدید قرض گرفته می شود. بیایید مثال ارث را از سخنرانی های قبلی به یاد بیاوریم:public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
public void gas() {
//...gas
}
public void brake() {
//...brake
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
برنامه خاصی وجود دارد که در آن با انواع مختلف خودروها کار می کنیم. حتی اگر از علاقه مندان به خودرو نیستید، احتمالاً می دانید که انواع بسیار زیادی از همین خودروها در جهان وجود دارد :) بنابراین، ما ویژگی های کلی خودروها را به یک کلاس اصلی والدین جدا می کنیم - Car
. وجه اشتراک همه خودروها صرف نظر از نوع آنها چیست؟ هر ماشینی یک سال ساخت، نام مدل و حداکثر سرعت دارد. ما این خصوصیات را در فیلدهای model
, maxSpeed
, قرار می دهیم yearOfManufacture
. در مورد رفتار هم هر ماشینی میتونه گاز بگیره و ترمز کنه :) این رفتار رو در روش ها gas()
و brake()
. این چه مزایایی برای ما دارد؟ اول از همه، کاهش مقدار کد. البته می توانیم بدون کلاس والد هم کار کنیم. اما از آنجایی که هر ماشینی باید بتواند شتاب بگیرد و ترمز کند، ما باید متدهایی را gas()
در brake()
کلاس Truck
، در کلاس Sedan
، در کلاس F1Car
، در کلاس Sportcar
و در همه کلاسهای دیگر خودروها ایجاد کنیم. تصور کنید در این مورد چقدر کد اضافی خواهیم نوشت. فیلدهای مدل، maxSpeed و yearOfManufacture را فراموش نکنید: اگر کلاس والد را رها کنیم، آنها را در هر یک از کلاسهای ماشین ایجاد خواهیم کرد! وقتی چند دوجین کلاس ماشین داریم، مقدار کدهای تکراری واقعا جدی می شود. جابجایی فیلدها و متدهای رایج (که به آنها "state" و "behavior" نیز میگویند) به کلاس والد به ما امکان میدهد در زمان و مکان زیادی صرفهجویی کنیم. اگر نوع خاصی دارای ویژگی ها یا روش هایی باشد که فقط مختص آن است و در سایر انواع ماشین ها وجود ندارد، مهم نیست. همیشه میتوان آنها را در یک کلاس از نسل، جدا از بقیه ایجاد کرد.
public class F1Car extends Car {
public void pitStop() {
//...only racing cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
اتومبیل های مسابقه فرمول 1 را در نظر بگیرید. آنها، بر خلاف "بستگان" خود، رفتار منحصر به فردی دارند - هر از گاهی برای توقف در پیت توقف می کنند. این ما را اذیت نمی کند. قبلاً رفتار کلی در کلاس والد را توضیح دادهایم Car
و میتوانیم رفتار خاصی از کلاسهای فرعی را در داخل کلاسها اضافه کنیم. این در مورد فیلدها نیز صدق می کند: اگر یک کلاس فرزند دارای ویژگی های منحصر به فرد باشد، می توانیم با آرامش این فیلدها را در داخل آن اعلام کنیم و نگران نباشیم :) امکان استفاده مجدد از کد مزیت اصلی ارث بردن است. برای یک برنامه نویس بسیار مهم است که مقادیر غیر ضروری کد ننویسد. شما بیش از یک بار در کار خود با این موضوع مواجه خواهید شد. لطفاً یک چیز بسیار مهم دیگر را به خاطر بسپارید: در جاوا وراثت چندگانه وجود ندارد. هر کلاس فقط از یک کلاس ارث می برد. ما در مورد دلایل این موضوع در سخنرانیهای آینده با جزئیات بیشتر صحبت خواهیم کرد، اما فعلاً فقط به یاد داشته باشید. این، به هر حال، جاوا را از برخی دیگر از زبان های OOP متمایز می کند. به عنوان مثال، C++ دارای وراثت چندگانه است. همه چیز با وراثت کم و بیش روشن است - بیایید ادامه دهیم.
ترکیب و تجمیع
کلاس ها و اشیا می توانند به یکدیگر مرتبط باشند. وراثت رابطه "است" (یا به انگلیسی "IS A") را توصیف می کند. لئو یک حیوان است. این رابطه را می توان به راحتی با استفاده از وراثت بیان کرد، جایی کهAnimal
کلاس والد و Lion
کلاس فرزند خواهد بود. با این حال، همه روابط در جهان به این شکل توصیف نمی شوند. به عنوان مثال، یک صفحه کلید قطعا به نوعی به یک کامپیوتر متصل است، اما یک کامپیوتر نیست . دست ها به نوعی با فرد مرتبط هستند، اما آن شخص نیستند. در این موارد، بر اساس نوع دیگری از رابطه است: نه "است"، بلکه "بخش است" ("HAS A"). دست یک شخص نیست، بلکه بخشی از یک شخص است. صفحه کلید یک کامپیوتر نیست، اما بخشی از کامپیوتر است. روابط HAS A را می توان در کد با استفاده از مکانیسم های ترکیب و تجمع توصیف کرد . تفاوت بین آنها در "دید بودن" این ارتباطات نهفته است. بیایید یک مثال ساده بیاوریم: ما مال خودمان داریم Car
- یک ماشین. هر ماشینی یک موتور دارد. علاوه بر این، هر خودرویی در داخل مسافران دارد. تفاوت اساسی بین فیلدها Engine engine
و Passenger [] passengers
? اگر خودرویی مسافری در داخل آن داشته باشد А
به این معنا نیست که نمی تواند مسافری در B
آن باشد C
. یک ماشین می تواند چندین مسافر را در خود جای دهد. علاوه بر این، اگر همه سرنشینان از خودرو خارج شوند، بی سر و صدا به کار خود ادامه می دهد. رابطه بین کلاس Car
و حجم مسافر Passenger [] passengers
کمتر سختگیرانه است. به آن تجمیع می گویند . مقاله خوبی در مورد این موضوع وجود دارد: روابط بین کلاس ها (اشیاء) . مثال خوب دیگری از تجمیع ارائه می دهد. فرض کنید یک کلاس داریم Student
که به دانش آموز اشاره می کند و یک کلاس StudentsGroup
(گروهی از دانش آموزان). یک دانش آموز می تواند عضو یک باشگاه فیزیک، یک باشگاه هواداران دانشجویی جنگ ستارگان یا یک تیم KVN باشد. ترکیب بندی نوعی ارتباط سختگیرانه تر است. هنگام استفاده از ترکیب، یک شی نه تنها بخشی از یک شی است، بلکه نمی تواند به شی دیگری از همان نوع نیز تعلق داشته باشد. ساده ترین مثال موتور ماشین است. موتور بخشی از یک ماشین است، اما نمی تواند بخشی از ماشین دیگری باشد. همانطور که می بینید، ارتباط آنها بسیار سخت تر از Car
و Passengers
.
GO TO FULL VERSION