Menu
Coddy logo textTech

Одиночное и многоуровневое наследование

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 25 из 87.

До сих пор мы видели, как классы расширяют один родительский класс напрямую. Но наследование может формировать различные структуры в зависимости от того, как классы связаны друг с другом. Давайте рассмотрим два основных паттерна: одиночное наследование и многоуровневое наследование.

Одиночное наследование — это то, что мы использовали до сих пор. Класс расширяет ровно один родительский класс напрямую:

public class Animal { }
public class Dog extends Animal { }
public class Cat extends Animal { }

Здесь и Dog, и Cat наследуются от Animal, но они не наследуются друг от друга. У каждого потомка есть один прямой родитель.

Многоуровневое наследование создает цепочку, в которой класс расширяет другой класс, который, в свою очередь, расширяет еще один класс:

public class Animal {
    public void eat() {
        System.out.println("Eating");
    }
}

public class Mammal extends Animal {
    public void breathe() {
        System.out.println("Breathing");
    }
}

public class Dog extends Mammal {
    public void bark() {
        System.out.println("Barking");
    }
}

В этой цепочке Dog наследуется от Mammal, которое наследуется от Animal. Объект Dog имеет доступ ко всем методам из всей цепочки:

Dog dog = new Dog();
dog.eat();      // От Animal
dog.breathe();  // От Mammal
dog.bark();     // От Dog

Помните, что Object находится на вершине каждой цепочки. Таким образом, наш Dog на самом деле имеет четыре уровня: Object -> Animal -> Mammal -> Dog. Цепочка конструкторов проходит через все эти уровни при создании нового объекта.

challenge icon

Задание

Легко

Давайте построим иерархию транспорта, которая демонстрирует как одиночное, так и многоуровневое наследование. Вы создадите цепочку классов, где каждый уровень добавляет новые возможности, показывая, как методы наследуются через несколько уровней.

Вы организуете свой код в четырех файлах:

  • Vehicle.java: Создайте базовый класс на вершине вашей иерархии. У каждого транспортного средства должно быть:
    • Приватное поле для brand (String)
    • Конструктор, принимающий бренд
    • Метод getBrand(), который возвращает бренд
    • Метод move(), который выводит: [brand] is moving
  • LandVehicle.java: Создайте класс, который расширяет Vehicle, представляя средний уровень вашей многоуровневой цепочки. Наземные транспортные средства добавляют специфическое для земли поведение:
    • Приватное поле для wheels (int)
    • Конструктор, который принимает brand и wheels, используя super(brand) для родительской части
    • Метод getWheels(), который возвращает количество колес
    • Метод honk(), который выводит: [brand] honks!
  • Car.java: Создайте класс, который расширяет LandVehicle, завершая вашу треххуровневую цепочку наследования. Автомобили добавляют свои собственные специализированные функции:
    • Приватное поле для model (String)
    • Конструктор, который принимает brand, wheels и model, используя super(brand, wheels)
    • Метод getModel(), который возвращает модель
    • Метод displayInfo(), который выводит: [brand] [model] with [wheels] wheels
  • Main.java: Продемонстрируйте, как объект Car имеет доступ к методам со всех трех уровней иерархии. Вы получите три входных значения: brand (String), wheels (int) и model (String). Создайте Car и вызовите эти методы по порядку:
    • move() — унаследован от Vehicle (прародитель)
    • honk() — унаследован от LandVehicle (родитель)
    • displayInfo() — определен в самом Car

Вы получите три входных значения: название бренда, количество колес и название модели.

Ваш вывод должен содержать три строки, демонстрирующие, как объект Car может использовать методы с каждого уровня своей цепочки наследования — от высокоуровневого Vehicle до своего собственного класса!

Шпаргалка

Java поддерживает различные структуры наследования. Двумя основными паттернами являются одиночное наследование и многоуровневое наследование.

Одиночное наследование происходит, когда класс расширяет ровно один родительский класс напрямую:

public class Animal { }
public class Dog extends Animal { }
public class Cat extends Animal { }

И Dog, и Cat наследуются от Animal, но не друг от друга.

Многоуровневое наследование создает цепочку, в которой класс расширяет другой класс, который, в свою очередь, расширяет еще один класс:

public class Animal {
    public void eat() {
        System.out.println("Eating");
    }
}

public class Mammal extends Animal {
    public void breathe() {
        System.out.println("Breathing");
    }
}

public class Dog extends Mammal {
    public void bark() {
        System.out.println("Barking");
    }
}

При многоуровневом наследовании дочерний класс имеет доступ ко всем методам из всей цепочки наследования:

Dog dog = new Dog();
dog.eat();      // От Animal
dog.breathe();  // От Mammal
dog.bark();     // От Dog

Каждая иерархия классов имеет Object на вершине. Цепочка вызовов конструкторов проходит через все уровни при создании нового объекта.

Попробуйте сами

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Считать входные данные
        String brand = scanner.nextLine();
        int wheels = scanner.nextInt();
        scanner.nextLine(); // пропустить символ новой строки
        String model = scanner.nextLine();
        
        // TODO: Создать объект Car с введенными значениями
        
        // TODO: Вызвать move() — унаследовано от Vehicle (прародитель)
        
        // TODO: Вызвать honk() — унаследовано от LandVehicle (родитель)
        
        // TODO: Вызвать displayInfo() — определено в самом Car
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование