سلام! در سخنرانی های قبلی قبلاً چندین بار به طور مختصر با مفهوم وراثت مواجه شده بودیم. امروز نیز به این موضوع خواهیم پرداخت، اما نه خیلی عمیق. بعداً یک سخنرانی مفصل در مورد این وجود خواهد داشت، اما امروز ما فقط به نمونه های عملی نگاه می کنیم و با یک اپراتور جالب در جاوا آشنا می شویم.
وراثت جاوا
بنابراین، ارث دقیقا چیست؟ وراثت مکانیزمی در برنامه نویسی از جمله جاوا است که به شما امکان می دهد یک کلاس جدید را بر اساس کلاس موجود توصیف کنید. سپس کلاس descendant به فیلدها و متدهای کلاس والد دسترسی پیدا می کند. چرا این ممکن است ضروری باشد؟ خوب، به عنوان مثال، تصور کنید که باید چندین کلاس از خودروها را در برنامه ایجاد کنید: کامیون، مسابقه، سدان، پیکاپ و غیره. حتی بدون شروع کدنویسی، مطمئناً می دانید که این کلاس ها اشتراکات زیادی دارند: همه خودروها دارای نام مدل، سال ساخت، حجم موتور، حداکثر سرعت و غیره هستند. (بدون ذکر این واقعیت که همه آنها دارای چرخ و سایر قطعات هستند). در چنین شرایطی می توانید:- این فیلدها را در هر کلاس ایجاد کنید و پس از ایجاد آنها به کلاس های جدید خودرو اضافه کنید
- فیلدهای مشترک برای همه ماشینها را به کلاس والد منتقل کنید
Car
و تمام کلاسهای انواع خاصی از ماشینها ازCar
استفاده از کلمه extends به ارث میبرند .
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 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);
}
}
حداقل از تکرار غیرضروری کد جلوگیری کرده ایم و این چیزی است که همیشه باید هنگام نوشتن برنامه ها برای آن تلاش کنیم. علاوه بر این، ما یک ساختار کلاس ساده و قابل درک داریم: فیلدهای مشترک برای همه ماشینها در یک کلاس قرار میگیرند. به عنوان مثال، اگر کامیون ها دارای فیلدهای خاصی هستند که سایر خودروها فاقد آن هستند، می توان آنها را در قسمت اعلام کرد Truck
. در مورد روش ها هم همینطور. همه خودروها رفتارهای مشترکی دارند که می توان آنها را توصیف کرد: ماشین را روشن کنید، گاز/ترمز و غیره. این روشهای کلی را میتوان در یک کلاس عمومی قرار داد Car
و رفتار خاص هر نوع خاص را میتوان در کلاسهای نسلی توصیف کرد.
public class Car {
public void gas() {
//...gas
}
public void brake() {
//...brake
}
}
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();
}
}
ما روش های رایج همه خودروها را به کلاس منتقل کرده ایم Car
. اما در کلاس جانشین F1Car
، که اتومبیل های مسابقه فرمول 1 را توصیف می کند - پیت استاپ (توقف هایی برای تعمیر و نگهداری فوری ماشین)، که فقط در مسابقات انجام می شود و با رفتار خاصی متمایز می شوند.
نمونه اپراتور جاوا
برای بررسی اینکه آیا یک شی بر اساس یک کلاس ایجاد شده است یا خیر، یک عملگر ویژه در جاوا وجود دارد -instanceof
. true
اگر تست درست بود یا false
اگر نتیجه غلط بود، مقدار را برمیگرداند . بیایید ببینیم که چگونه با استفاده از کلاس های اتومبیل ما به عنوان مثال کار می کند:
public class Truck extends Car {
public static void main(String[] args) {
Truck truck = new Truck();
System.out.println(truck instanceof Car);
}
}
خروجی: true چک با استفاده از اپراتور instanceof
برگردانده شد true
، زیرا ما یک شی از کلاس داریم Truck
و همه کامیون ها اتومبیل هستند. این کلاس Truck
از نوادگان این کلاس است Car
، بنابراین، همه کامیون ها بر اساس یک والدین مشترک - یک ماشین ایجاد می شوند. به عملگر توجه کنید instanceof
: بدون نقطه نوشته شده است، زیرا یک عملگر است، نه یک متد ("مثلا شیء کلاس"). بیایید آن را متفاوت امتحان کنیم:
public static void main(String[] args) {
Car car = new Car();
System.out.println(car instanceof Truck);
}
خروجی: false کلاس Car
و بر این اساس، هدف آن از کلاس نشات نمیگیرد Truck
. همه کامیونها خودرو هستند، اما همه خودروها کامیون نیستند. اشیاء Car
بر اساس کلاس ایجاد نمی شوند Truck
. یک مثال دیگر:
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
System.out.println(car instanceof Object && truck instanceof Object);
}
خروجی: True منطق در اینجا نیز ساده است: همه کلاسهای جاوا، از جمله کلاسهایی که ایجاد کردهاید، از یک کلاس میآیند (اگرچه شما Extends Object راObject
در آنها نمینویسید - این مکانیسم در آنها به طور ضمنی وجود دارد). چرا این ممکن است مفید باشد و تحت چه شرایطی؟ رایج ترین استفاده از اپراتور به عنوان یک روش لغو است . به عنوان مثال، در اینجا نحوه پیاده سازی متد در کلاس آمده است : instanceof
equals()
equals
String
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
قبل از مقایسه رشته با شی ارسال شده، روش بررسی می کند: آیا شیء ارسال شده در واقع یک رشته است؟ و تنها پس از آن او شروع به مقایسه خواص دو شی می کند. بدون این بررسی، می توانید هر شی که دارای فیلدهای مقدار و طول باشد را به متد ارسال کنید و آن را با یک رشته مقایسه کنید، که البته اشتباه است.
GO TO FULL VERSION