JavaRush /Java блог /Random UA /instanceof і основи наслідування

instanceof і основи наслідування

Стаття з групи Random UA
Вітання! У попередніх лекціях ми вже кілька разів мигцем зустрічалися з таким поняттям, як спадкування. Сьогодні ми теж торкнемося цієї теми, але теж не надто глибоко. Детальна лекція про це ще буде, а сьогодні швидше просто подивимося практичні приклади та познайомимося з одним цікавим оператором Java.

Успадкування Java

Отже, що таке, власне, успадкування? встанівід основи успадкування - 1Спадкування - це механізм у програмуванні, у тому числі і в 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 , і порівнювати його з рядком, що, звичайно, було б неправильно.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ