Рубрики
Без рубрики

Учебник по наследованию Java: объясняется на примерах

Наследование – это процесс создания нового класса на основе функций другого существующего класса. I… С пометкой java, учебник, ооп.

Наследование – это процесс создания нового класса на основе функций другого существующего класса. Он широко используется в Java, Python и других объектно-ориентированных языках для повышения возможности повторного использования кода и упрощения логики программы в категориальных и иерархических отношениях.

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

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

Вот что мы рассмотрим сегодня:

  • Что такое наследование?
  • Наследование в Java
  • Примеры наследования Java
  • Продвинутые концепции для изучения следующий

Внедряйте Java в два раза быстрее

Получите практическую практику с нашим лучшим контентом Java, адаптированным к текущему уровню квалификации разработчиков.

Java для программистов

Что такое наследование?

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

Наследование имеет важное значение для продвинутого Объектно-ориентированное программирование (ООП), поскольку оно позволяет повторно использовать функции одного класса в вашей программе без репликации кода.

Наследование часто используется для представления категорий (родительских классов) и подкатегорий (подклассов). Родительский класс задает функции, присутствующие во всех объектах, независимо от подкатегории, в то время как каждый подкласс представляет меньшую, более конкретную категорию.

Например, вы могли бы создать класс Автомобиль который указывает колеса и подкласс Седан , который включает в себя атрибут двери . Поток отношений наследования часто отражает логические отношения, аналогичные квадратам и прямоугольникам; в этом случае все седаны являются автомобилями, но не все автомобили являются седанами.

Наследование имеет три основных преимущества:

  1. Возможность повторного использования: Наследование позволяет повторно использовать функции существующего класса неограниченное количество раз в любом классе, который наследует этот класс. Вы можете сохранить согласованную функциональность для всех объектов одного типа, не переписывая код.
  2. Структура кода: Наследование обеспечивает четкую, понятную логическую структуру для вашей программы. Это позволяет разработчикам понимать ваш код как набор связанных, но уникальных категорий, а не просто как блок кода.
  3. Скрытие данных: Базовый класс может быть настроен на сохранение некоторых данных в тайне, чтобы они не могли быть изменены производным классом. Это пример инкапсуляции, когда доступ к данным ограничен только теми классами, которые нуждаются в них для своей роли.

Наследование в Java

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

Подклассы связаны с суперклассами с помощью ключевого слова extends при их определении. Подклассы могут определять новые локальные методы или поля для использования или могут использовать ключевое слово super для вызова унаследованных методов или суперконструктора.

class b {
// implementation of inheritedMethod()
}
class a extends b
{  
   inheritedMethod();
}  

Когда использовать супер ключевое слово

супер – это, по сути, кнопка “предыдущее значение”, вызываемая из дочернего класса, которая позволяет вам читать и получать доступ к функциям родительского класса независимо от их значения в текущем дочернем классе.

Ключевое слово супер используется для:

  • Доступ к полям родительского класса : super.var считывает значение var , заданное в родительском классе, в то время как var самостоятельно считывает измененное значение из дочернего класса.
  • Вызов метода родительского класса : super.method() позволяет дочернему классу получить доступ к реализации родительского класса method() . Это требуется только в том случае, если дочерний класс также имеет метод с тем же именем.
  • Использование конструкторов : Это позволяет создавать новые экземпляры родительского класса из дочернего класса.

Напомним, что конструкторы в Java – это специальные методы, используемые для инициализации объектов. Вызов суперконструктора создает новый объект, для которого требуются все поля, определенные в конструкторе родительского класса.

Затем вы можете добавить дополнительные поля в другие инструкции, чтобы сделать дочерний экземпляр более конкретным, чем родительский. По сути, это позволяет вам использовать конструктор родительского класса в качестве шаблона для конструктора дочернего класса.

    public Car(String make, String color, int year, String model, String bodyStyle) {
        super(make, color, year, model);  //parent class constructor
        this.bodyStyle = bodyStyle;       
    }

Типы наследования

В Java доступно несколько типов наследования:

  • Одиночное наследование – это когда один подкласс наследуется от суперкласса, образуя один уровень наследования.

  • Многоуровневое наследование – это когда суперкласс наследуется промежуточным классом, который затем наследуется производным классом, образуя 3 или более уровней наследования.

  • Иерархическое наследование – это когда один суперкласс служит основой для нескольких конкретных подклассов. Это наиболее распространенная форма наследования.

Существуют также два других типа наследования, которые доступны только в Java благодаря сочетанию наследования классов и интерфейсов.

  • Множественное наследование , когда один подкласс наследуется от нескольких родительских классов.

  • Гибридное наследование , смесь двух или более из вышеперечисленных видов наследования.

Java не поддерживает множественное наследование с классами, что означает, что оба этих типа наследования невозможны только с классами Java. Однако подкласс может наследовать более одного интерфейса (абстрактный класс). Таким образом, вы можете имитировать множественное наследование, если вы объедините использование интерфейсов и классов.

Примеры наследования Java

Чтобы помочь вам лучше понять наследование, давайте перейдем к некоторым примерам кода. Обратите внимание на синтаксические компоненты наследования, которые мы видели до сих пор, такие как супер и общие методы.

Чтобы объявить наследование в Java, мы просто добавляем extends [суперкласс] после идентификатора подклассов.

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

// Base Class Vehicle
class Vehicle {

  // Private Fields
  private String make; 
  private String color; 
  private int year;      
  private String model;   


  // Parameterized Constructor
  public Vehicle(String make, String color, int year, String model) {
    this.make = make;
    this.color = color;
    this.year = year;  
    this.model = model; 
  }

  // public method to print details
  public void printDetails() {
    System.out.println("Manufacturer: " + make);
    System.out.println("Color: " + color);
    System.out.println("Year: " + year);
    System.out.println("Model: " + model);
  }

}

// Derived Class Car
class Car extends Vehicle {

  // Private field
  private String bodyStyle;

  // Parameterized Constructor
  public Car(String make, String color, int year, String model, String bodyStyle) {
    super(make, color, year, model);  //calling parent class constructor
    this.bodyStyle = bodyStyle;       
  }

  public void carDetails() {  //details of car
    printDetails();         //calling method from parent class
    System.out.println("Body Style: " + bodyStyle);
  }

}

class Main {

  public static void main(String[] args) {
    Car elantraSedan = new Car("Hyundai", "Red", 2019, "Elantra", "Sedan"); //creation of car Object
    elantraSedan.carDetails(); //calling method to print details
  }

}

Это пример одинарного наследования, так как только один объект наследуется от родительского класса. В строке 37 вы можете видеть , что мы используем super для вызова конструктора суперкласса , который упрощает наш конструктор Car . Вы также можете увидеть, как Автомобиль имеет доступ к классу транспортного средства методу printDetails() в строке 42 .

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

Приведение типов в Java

Java также позволяет ссылаться на подкласс как на экземпляр его суперкласса, по сути, рассматривая подкласс так, как если бы он принадлежал к типу суперкласса. Этот процесс известен как приведение типов . Это отличный способ создания модульного кода, так как вы можете написать код, который будет работать для любого подкласса одного и того же родителя. Например, вы можете ссылаться на переменную типа Автомобиль как на объект типа Транспортное средство .

Car car     = new Car();
Vehicle vehicle = car;

Сначала мы создаем экземпляр Car , а затем присваиваем этот экземпляр переменной типа Vehicle . Теперь ссылка на переменную Vehicle указывает на экземпляр Car . Это позволяет вам обрабатывать любой подкласс Транспортного средства как то же самое Транспортное средство тип, даже если вы не знаете к какому подклассу Транспортного средства он относится. Существует два типа типизации: восходящая и нисходящая.

Повышение – это когда вы обращаетесь с дочерним классом так, как если бы он был экземпляром родительского класса, как в нашем предыдущем примере. Любые поля, уникальные для дочернего класса, будут скрыты, чтобы они соответствовали форме родительского класса.

Понижение – это когда вы обращаетесь с экземпляром родительского класса так, как если бы он был одним из его дочерних классов. В то время как любой подкласс может быть повышен, только объекты, которые изначально были типизированы для подкласса, могут быть понижены.

Другими словами, объект может быть понижен, если объект изначально принадлежал к типу подкласса, но позже был повышен до родительского класса.

//valid code
Car car = new Car();
// upcast to Vehicle
Vehicle vehicle = car;
// downcast to car again
Car car2 =  (Car) vehicle;

Переданный объект по-прежнему сохраняет поля, которые у него были, и поэтому может быть добавлен обратно, чтобы снова сделать его допустимым объектом типа дочернего класса.

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

Переопределение методов в Java

Иногда нам понадобится один из наших подклассов, чтобы изменить поведение унаследованного метода. Java позволяет нам делать это, переопределяя существующие методы путем создания новых методов с тем же именем. Это также позволяет нам предоставлять классовые реализации абстрактных методов из интерфейсов.

class Parent {
  void myMethod() {
    //original implementation
  }
}
class Child extends Parent {
  @override
  void myMethod() {
    //new implementation
  }
}

Переопределение методов является фундаментальным инструментом при реализации полиморфизма, принципа проектирования, который позволяет разным классам иметь уникальные реализации для одного и того же метода. Если мы разберем это слово, то “поли” означает “много”, а “морф” означает “форма”.

Проще говоря, полиморфизм означает наличие множества специфичных для класса форм процесса для выполнения одной и той же задачи.

Вот функции, которыми должна обладать программа, чтобы разрешить переопределение методов:

  • Переопределение метода требует наследования, и должен быть хотя бы один производный класс.
  • Производные классы должны иметь такое же объявление, т.е. модификатор доступа, имя, те же параметры и тот же тип возвращаемого метода, что и у базового класса.
  • Метод в производном классе или классах должен иметь реализацию, отличную друг от друга.
  • Метод в базовом классе должен быть переопределен в производном классе.
  • Базовый класс/метод не должен быть объявлен как Конечный класс. Чтобы переопределить метод в Java, определите новый метод с тем же именем, что и метод, который вы хотите переопределить, и добавьте @Переопределить тег над ним.

Здесь вы можете увидеть пример того, как мы можем создать поведение, зависящее от класса, для одного и того же вызова метода. Наш вызов метода всегда get Area() однако реализация метода зависит от класса оцениваемой фигуры.

// A sample class Shape which provides a method to get the Shape's area
class Shape {
  public double getArea() {
    return 0;
  }
}
// A Rectangle is a Shape with a specific width and height
class Rectangle extends Shape {   // extended form the Shape class
  private double width;
  private double height;
  public Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
  }
  public double getArea() {
    return width * height; 
  }
}
// A Circle is a Shape with a specific radius
class Circle extends Shape {
  private double radius;
  public Circle(double radius) {
    this.radius = radius; 
  }
  public double getArea() {
    return 3.14 * radius * radius; 
  }
}
class driver {
  public static void main(String args[]) {
    Shape[] shape = new Shape[2]; // Creating shape array of size 2
    shape[0] = new Circle(2); // creating circle object at index 0
    shape[1] = new Rectangle(2, 2); // creating rectangle object at index 1
    // Shape object is calling children classes method
    System.out.println("Area of the Circle: " + shape[0].getArea());
    System.out.println("Area of the Rectangle: " + shape[1].getArea());
  }
}

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

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

Последнее ключевое слово

В Java ключевое слово final может использоваться при объявлении переменной, класса или метода, чтобы сделать значение неизменным. Значение сущности определяется при инициализации и будет оставаться неизменным на протяжении всей программы. Попытка изменить значение чего-либо, объявленного как final , приведет к ошибке компилятора.

// declaring a final variable
class FinalVariable {
        final int var = 50;
        var = 60 //This line would give an error
}

Точное поведение final зависит от типа сущности:

  • финал Параметр не может быть изменен нигде в функции
  • окончательный Метод не может быть переопределен или скрыт каким-либо подклассом
  • окончательный Класс не может быть родительским классом для любого подкласса
final boolean immutable = true;
boolean mutable = immutable;

Хотя значение сущностей final изменить нельзя, их можно использовать для установки значений переменных, не относящихся к final . Это свойство делает его полезным для решения проблем изменчивости данных, когда для функционирования нескольких разделов кода необходимо ссылаться на один и тот же объект.

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

Продвинутые концепции для изучения следующий

Наследование является мощным инструментом в Java и имеет важное значение для понимания передовых конструкций ООП. Некоторые следующие концепции, которые следует изучить на вашем пути разработки Java, следующие:

  • Абстракция и интерфейсы
  • Агрегация
  • Композиция
  • API-интерфейсы Java 8
  • Расширенные модификаторы доступа

Чтобы помочь вам понять эти и другие передовые концепции, мы создали Java для разработчиков Путь . Внутри вы найдете коллекцию нашего лучшего контента на Java по таким темам, как ООП, многопоточность, рекурсия и новые функции Java 8. Эти уроки выбраны из всей нашей библиотеки курсов, что позволяет вам учиться на наших лучших материалах для каждой концепции.

К концу у вас будут навыки и практический опыт, необходимые для успешного прохождения следующего собеседования на Java.

Счастливого обучения!

Продолжайте читать о Java

Оригинал: “https://dev.to/educative/java-inheritance-tutorial-explained-with-examples-5ck8”