Наследование в Java является одним из основных концепций объектно-ориентированного программирования. Наследование в Java используется, когда у нас есть отношение is-a между объектами. Наследование в Java реализуется с использованием ключевого слова extends
.
Наследование в Java
Наследование в Java – это способ создания иерархии между классами путем наследования от других классов.
Наследование в Java является транзитивным – так что, если Sedan расширяет Car, а Car расширяет Vehicle, то Sedan также унаследован от класса Vehicle. Vehicle становится суперклассом как для Car, так и для Sedan.
Наследование широко используется в приложениях на Java, например, при расширении класса Exception для создания класса исключения, специфичного для приложения, который содержит дополнительную информацию, такую как коды ошибок. Например, NullPointerException.
Пример наследования в Java
Каждый класс в Java неявно расширяет класс java.lang.Object
. Так что класс Object находится на вершине иерархии наследования в Java.
Давайте посмотрим, как реализовать наследование в Java на примере.
Суперкласс: Animal
package com.journaldev.inheritance;
public class Animal {
private boolean vegetarian;
private String eats;
private int noOfLegs;
public Animal(){}
public Animal(boolean veg, String food, int legs){
this.vegetarian = veg;
this.eats = food;
this.noOfLegs = legs;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public String getEats() {
return eats;
}
public void setEats(String eats) {
this.eats = eats;
}
public int getNoOfLegs() {
return noOfLegs;
}
public void setNoOfLegs(int noOfLegs) {
this.noOfLegs = noOfLegs;
}
}
Животное является базовым классом здесь. Давайте создадим класс Cat, который наследует от класса Animal.
Подкласс: Cat
package com.journaldev.inheritance;
public class Cat extends Animal{
private String color;
public Cat(boolean veg, String food, int legs) {
super(veg, food, legs);
this.color="White";
}
public Cat(boolean veg, String food, int legs, String color){
super(veg, food, legs);
this.color=color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
Обратите внимание, что мы используем ключевое слово extends
для реализации наследования в Java.
Тестовая программа наследования в Java
Давайте напишем простой тестовый класс, чтобы создать объект Cat и использовать некоторые из его методов.
package com.journaldev.inheritance;
public class AnimalInheritanceTest {
public static void main(String[] args) {
Cat cat = new Cat(false, "milk", 4, "black");
System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
System.out.println("Cat eats " + cat.getEats());
System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
System.out.println("Cat color is " + cat.getColor());
}
}
Вывод:
У класса Cat нет метода getEats()
, но программа всё равно работает, потому что он унаследован от класса Animal.
Важные моменты
-
Повторное использование кода – самое важное преимущество наследования, потому что подклассы наследуют переменные и методы суперкласса.
-
Приватные члены суперкласса не доступны напрямую подклассу. Как в этом примере, переменная Animal noOfLegs не доступна классу Cat, но она может быть косвенно доступна через методы getter и setter.
-
Члены суперкласса с доступом по умолчанию доступны подклассу ТОЛЬКО если они находятся в том же пакете.
-
Конструкторы суперкласса не наследуются подклассом.
-
Если у суперкласса нет конструктора по умолчанию, то подкласс также должен иметь явно определенный конструктор. В противном случае будет выброшено исключение времени компиляции. В конструкторе подкласса вызов конструктора суперкласса обязателен в этом случае и должен быть первым оператором в конструкторе подкласса.
-
Java не поддерживает множественное наследование, подкласс может расширять только один класс. Класс Animal неявно расширяет класс Object, а класс Cat расширяет класс Animal, но из-за транзитивной природы наследования в Java класс Cat также расширяет класс Object.
-
Мы можем создать экземпляр подкласса и затем присвоить его переменной суперкласса, это называется повышающим приведением типа. Ниже приведен простой пример повышающего приведения типа:
Cat c = new Cat(); // экземпляр подкласса Animal a = c; // повышающее приведение типа, это нормально, так как Cat также является Animal
-
Когда экземпляр Superclass присваивается переменной Subclass, это называется downcasting. Нам нужно явно приводить его к Subclass. Например;
Cat c = new Cat(); Animal a = c; Cat c1 = (Cat) a; // явное приведение, работает хорошо, потому что "c" фактически имеет тип Cat
Обратите внимание, что компилятор не будет жаловаться, даже если мы делаем что-то неправильно, из-за явного приведения. Вот несколько случаев, когда это вызовет исключение
ClassCastException
во время выполнения.Dog d = new Dog(); Animal a = d; Cat c1 = (Cat) a; //ClassCastException во время выполнения Animal a1 = new Animal(); Cat c2 = (Cat) a1; //ClassCastException, потому что a1 фактически имеет тип Animal во время выполнения
-
Мы можем переопределить метод Superclass в Subclass. Однако мы всегда должны аннотировать переопределенный метод аннотацией @Override. Компилятор узнает, что мы переопределяем метод, и если что-то изменится в методе суперкласса, мы получим ошибку времени компиляции, а не нежелательные результаты во время выполнения.
-
Мы можем вызывать методы суперкласса и получать доступ к переменным суперкласса с использованием ключевого слова super. Это пригодится, когда у нас есть переменная/метод с тем же именем в подклассе, но мы хотим получить доступ к переменной/методу суперкласса. Это также используется, когда конструкторы определены в суперклассе и подклассе, и нам нужно явно вызвать конструктор суперкласса.
-
Мы можем использовать инструкцию
instanceof
, чтобы проверить наследование между объектами, давайте посмотрим на пример ниже.
```
Cat c = new Cat();
Dog d = new Dog();
Animal an = c;
boolean flag = c instanceof Cat; //normal case, returns true
flag = c instanceof Animal; // returns true since c is-an Animal too
flag = an instanceof Cat; //returns true because a is of type Cat at runtime
flag = an instanceof Dog; //returns false for obvious reasons.
```
- Мы не можем расширять конечные классы в Java.
- Если вы не собираетесь использовать Superclass в коде, то есть ваш Superclass является всего лишь базой для хранения повторно используемого кода, тогда вы можете сохранить их как Абстрактный класс, чтобы избежать ненужного создания экземпляров клиентскими классами. Это также ограничит создание экземпляров базового класса.
Видеоурок по наследованию в Java
I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.
Вы можете ознакомиться с большим количеством примеров наследования в нашем репозитории GitHub.
Ссылка: Документация Oracle
Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example