Вітання! У попередніх лекціях ми вже кілька разів мигцем зустрічалися з таким поняттям, як спадкування. Сьогодні ми теж торкнемося цієї теми, але теж не надто глибоко. Детальна лекція про це ще буде, а сьогодні швидше просто подивимося практичні приклади та познайомимося з одним цікавим оператором Java.
Успадкування Java
Отже, що таке, власне, успадкування? Спадкування - це механізм у програмуванні, у тому числі і в Java, який дозволяє описати новий клас на основі вже існуючого. Клас-спадкоємець при цьому отримує доступ до полів та методів батьківського класу. Навіщо це може бути потрібне? Ну, наприклад, уяви, що тобі потрібно створити в програмі кілька класів машин: Вантажівка, Гоночна, Седан, Пікап і т.д. Навіть не приступивши до написання коду, ти точно знаєш, що ці класи мають дуже багато спільного: у всіх машин є назва моделі, рік випуску, об'єм двигуна, максимальна швидкість і т.д. (Не кажучи вже про те, що у них є колеса та інші деталі). У такій ситуації ти можеш:- Створювати ці поля у кожному класі та додавати їх у нові класи машин при їх створенні
- Винести загальні для всіх машин поля в батьківський клас
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() {
//...газ
}
public void brake() {
//...гальмо
}
}
public class F1Car extends Car {
public void pitStop() {
//...піт-стоп роблять тільки гоночні автомобілі
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
Ми винесли загальні методи всіх автомобілів у клас Car
. А ось у клас-спадкоємець F1Car
, який описує гоночні автомобілі "Формули-1" - піт-стопи (зупинки для термінового обслуговування машини), які роблять тільки в гонках та вирізняються специфічною поведінкою.
Оператор instanceof Java
Для перевірки того, чи створено об'єкт на основі якогось класу, Java існує спеціальний оператор —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
: він пишеться без точки, оскільки це саме оператор, а не метод (“об'єкт 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 Тут логіка теж проста: всі класи в Java, включаючи ті, які ти створив, походить від класу Object
(хоча ти і не пишеш у них extends 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;
}
Перш ніж порівняти рядок з переданим об'єктом, метод перевіряє: а чи є власне переданий об'єкт рядком? І тільки потім він починає порівнювати властивості двох об'єктів. Без цієї перевірки метод можна було б передати будь-який об'єкт, у якого є поля value і length , і порівнювати його з рядком, що, звичайно, було б неправильно.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ