Ковариантность возвращаемых типов при переопределениие методов в Java
Сегодня поиграемся с переопределением методов и разберемся, что такое ковариантность.
Итак, при переопределении методов (overriding) сигнатуры методов должны совпадать. В сигнатуру методов входит имя метода и его параметры. Возвращаемые параметры, туда не входят. За одним исключением, а именно метод в котором делается переопределение, может возвращать не только сам объект, но и его потомков. именно это и называется страшным словом ковариантность.
Под ковариантность подразумевается, что переопределённый метод может вернуть тип, производный от типа, возвращаемого методом базового класса.
Как всегда, начну с примера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
public class Main { public static void main(String[] args) { Employee [] managers = new Employee [6]; managers[0] = new Employee( new Dude() ); managers[1] = new Employee( new Boy() ); managers[2] = new Employee( new Girl() ); managers[3] = new Manager( new Dude() ); managers[4] = new Manager( new Boy() ); managers[5] = new Manager( new Girl() ); for (Employee m : managers) { System.out.println("Sex: " + m.getPerson() ); } } } class Manager extends Employee { Manager(Person person) { super(person); } @Override public Dude getPerson() { System.out.print("Manager.getPerson() --> "); return (Dude) person; } } class Employee { protected Person person; Employee(Person person) { this.person = person; } public Person getPerson() { System.out.print("Employee.getPerson() --> "); return person; } } abstract class Person { protected String sex=""; @Override public abstract String toString(); } class Dude extends Person { protected String sex = "asexual"; @Override public String toString() { return sex; } } class Boy extends Dude { protected String sex = "male"; @Override public String toString() { return sex; } } class Girl extends Dude { protected String sex = "female"; @Override public String toString() { return sex; } } |
Результат:
1 2 3 4 5 6 7 8 |
Employee.getPerson() --> Sex: asexual Employee.getPerson() --> Sex: male Employee.getPerson() --> Sex: female Manager.getPerson() --> Sex: asexual Manager.getPerson() --> Sex: male Manager.getPerson() --> Sex: female |
Как видим в классе Employee, метод getPerson возвращает тип Person. А в наследнике Employee, классе Manager, в переопределенном методе, мы возвращаем уже класс Dude. В выводе мы вывели название вызываемых классов, поэтому видим что переопределение работает.
Вывод: При переопределении (overriding) сигнатуры методов должны совпадать. Возвращаемый тип должен либо совпадать, либо быть потомком первоначально выбранного объекта (ковариантные типы).
Author: | Tags: /
| Rating:
1 comment.
Write a comment