2016-03-08 4 views
2

В java почему допустимы типы ковариантных возвращаемых значений, если несовместимые типы возвращаемых данных генерируют ошибку времени компиляции. Разумеется, если JVM может обрабатывать ковариантные типы возвращаемых данных, тогда он может обрабатывать нековариантные типы возврата. Я полагаю, что когда java видит переопределенный метод с ковариантным возвратом, он просто применяет метод, связанный с вызывающим объектом. Почему это не может произойти с не ковариантными типами возврата. Я предполагаю, что это связано с нарушением условий контракта на суперкласс и, конечно, если это было разрешено, поведение методов подкласс (переопределенных) не очень предсказуемо (поскольку в обратном типе нет согласованности)?Возврат к Java-варианту Java

Вот пример (предположит, что собачий является подклассом еды, но Catfood не является подкласс еды):

класса Animal

public class Animal { 

public Food seekFood() { 

    return new Food(); 
} 
} 

класса Dog

public class Dog extends Animal { 

public DogFood seekFood() { //This is OK since its a covariant 

    return new DogFood(); 
} 
} 

класса Cat

public class Cat extends Animal { 

public CatFood seekFood() { // This won't compile. Catfood is not covariant 

    return new CatFood(); 
} 
} 
+2

Я не получил вашу точку на самом деле. Это может быть хороший вопрос, но, пожалуйста, объясните это одним примером .. Нам было бы лучше для всех нас. –

ответ

0

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

UPDATE: Javac компилирует методы совместного вариантных свои методы класса базировать, когда вы делаете вызов к нему делегаты метода базового класса вызова методу подкласса. Поскольку они возвращают разные типы, приведение типов невозможно. Благодаря A. Sundararajan's Weblog, этот процесс можно объяснить очень четко с одним фрагментом коды:

class CircleFactory extends ShapeFactory { 
    public Circle newShape() { 
     // your code from the source file 
     return new Circle(); 
    } 

    // javac generated method in the .class file 
    public Shape newShape() { 
     // call the other newShape method here -- invokevirtual newShape:()LCircle; 
    } 
} 
+0

В моем примере все три метода имеют одну и ту же подпись. Однако все они имеют разные типы возврата. В случае коварианта компилятор не жалуется и может выбрать способ вызова; он определяет, какой метод вызывать на основе типа объекта. В примере Cat Catfood не является ковариантом Food, и, следовательно, метод catFoodFood не компилируется. Почему это? Я подозреваю, что JVM может относиться к нему как ковариант, но если бы это было так, я предполагаю, что у вас будет непредсказуемый/тесно связанный код? – Risteard

0
class A { 
    Ra f(Pa x) { ... } 
} 

class B extends A { 
    @Override 
    Rb f(Pb x) { ... } 
} 

Правила наследования определяет со-вариант/противопоказан вариант поведение:

значение типа T может назначаться только переменной типа T или родительскому типу.

Вызов метода подразумевает назначение его фактических аргументов метода (1) локальным параметрам (2) и присвоение значения результата (1) некоторому месту (2), которое будет использоваться.

Теперь, если компилятор встречает объект A, который фактически может представлять собой В, то из этого следует за B.f быть допустимым переопределение:

  1. Pb может быть только действительным, когда он Па или родительский класс (противопоказаны вариант);

    Потому что вы B.f должны быть в состоянии получить хотя бы значение Pa.

  2. Rb может быть действительным только в том случае, если это Ra или дочерний класс (со-вариант);

    Поскольку B.f должен возвращать то, что назначается Ra.

Это делает класс ребенка более ограничительным, конкретным.

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

Смежные вопросы