Повышающее и понижающее преобразование - важная часть Java, которая позволяет нам создавать сложные программы с использованием простого синтаксиса и дает нам большие преимущества, такие как полиморфизм или группировка различных объектов. Java позволяет рассматривать объект типа подкласса как объект любого типа суперкласса. Это называется апкастингом. Повышение качества выполняется автоматически, а понижающее преобразование должно выполняться программистом вручную , и я постараюсь объяснить, почему это так.
Повышение и понижающее приведение НЕ похожи на приведение примитивов от одного к другому, и я считаю, что это вызывает большую путаницу, когда программист начинает изучать приведение объектов.
Полиморфизм: все методы в java по умолчанию виртуальные. Это означает, что любой метод может быть переопределен при использовании в наследовании, если этот метод не объявлен как final или static .
Ниже вы можете увидеть пример getType();
работы в зависимости от типа объекта (Dog, Pet, Police Dog).
Предположим, у вас есть три собаки
Собака - это суперкласс.
Pet Dog - Собака расширяет Dog.
Police Dog - Полицейская собака расширяет Pet Dog.
public class Dog{
public String getType () {
System.out.println("NormalDog");
return "NormalDog";
}
}
public class PetDog extends Dog{
public String getType () {
System.out.println("PetDog");
return "PetDog";
}
public String dogName () {
System.out.println("I don't have Name !!");
return "NO Name";
}
}
public class PoliceDog extends PetDog{
public String secretId() {
System.out.println("ID");
return "ID";
}
public String getType () {
System.out.println("I am a Police Dog");
return "Police Dog";
}
}
Полиморфизм: все методы в java по умолчанию виртуальные. Это означает, что любой метод может быть переопределен при использовании в наследовании, если только этот метод не объявлен как final или static (объяснение относится к концепции виртуальных таблиц)
Виртуальная таблица / таблица отправки: таблица отправки объекта будет содержать адреса динамически связанных методов объекта. Вызов метода выполняется путем выборки адреса метода из диспетчерской таблицы объекта. Таблица диспетчеризации одинакова для всех объектов, принадлежащих к одному классу, и поэтому обычно используется ими совместно.
public static void main (String[] args) {
Dog obj1 = new Dog();
`
Dog obj2 = new PetDog();
`
Dog obj3 = new PoliceDog();
}
obj1.getType();
Печать Normal Dog
obj2.getType();
Печать Pet Dog
obj3.getType();
Печать Police Dog
Понижающее значение должно выполняться программистом вручную
Когда вы пытаетесь вызвать secretID();
метод, на obj3
который есть PoliceDog object
ссылка, Dog
который является суперклассом в иерархии, он выдает ошибку, поскольку obj3
у него нет доступа к secretId()
методу. Чтобы вызвать этот метод, вам необходимо вручную отключить этот obj3, чтобы PoliceDog
( (PoliceDog)obj3).secretID();
который печатает ID
Аналогичным образом для вызова dogName();
метода в PetDog
классе необходимо обратное приведение obj2
к PetDog
так obj2 отсчитываются Dog
и не имеет доступ к dogName();
методе
( (PetDog)obj2).dogName();
Почему так происходит автоматическое преобразование с повышением частоты, а с понижением - вручную? Видите ли, апкастинг никогда не подводит. Но если у вас есть группа различных собак и хотят их всех обратное приведение к их типу, то есть шанс, что некоторые из этих собак на самом деле различных типов , то есть, PetDog
, PoliceDog
и процесс выходит из строя, путем метания ClassCastException
.
Это причина, по которой вам нужно вручную понижать качество ваших объектов, если вы связали свои объекты с типом суперкласса.
Примечание: здесь ссылка означает, что вы не меняете адрес памяти своих объектов, когда вы его понижаете, он все равно остается таким же, вы просто группируете их по определенному типу в этом случае Dog
Dog
- это файлAnimal
. В большинстве случаев апкастинг не требуется, если вы не хотите использовать определенный перегруженный метод.callme
существует в обоихAnimal
иDog
.callme2
существует только вDog
, которые вы приводите ,a
чтобыDog
сделать его работу.