2016-05-25 7 views
0

Ich habe alle Informationen gelesen, kann aber immer noch nicht den Grund finden, warum in diesem grundlegenden Beispiel das Überschreiben nicht möglich ist. Bitte erkläre.Das einfachste Beispiel für das Überschreiben von Methoden mit Generics

class Fruit{} 
class Apple extends Fruit{} 

class Parent { 
    public Set<Fruit> getIt(){ 
    return null; 
    } 
} 

class Child extends Parent { 
    @Override // THIS DOESN'T WORK 
    public Set<Apple> getIt(){ 
     return null; 
    } 
} 

Antwort

2

Weil es zwingende nicht. Was Sie wollen, heißt Kovarianz. Das bedeutet, dass Sie als Rückgabetyp Set<Apple> der Überschreibmethode einer Unterklasse Child einen Untertyp des Rückgabetyps der ursprünglichen Methode Set<Fruit> der Klasse Parent verwenden möchten.

Aber leider ist Set<Apple> kein Subtyp von Set<Fruit> in Java, auch wenn Apple ein Subtyp von Fruit ist. Für einen sehr einfachen Grund: Sie können jede Fruit zu einem Set<Fruit>, hinzufügen, wenn Set<Apple> eine Set<Fruit> waren dann würden Sie eine Banana zu einem Set<Apple> wie alles möglich in einer Superklasse in einer Unterklasse möglich hinzuzufügen, in der Lage ist ...

Also Set<Fruit> und Set<Apple> sind nicht verwandte Typen, und dies verbietet das Überschreiben.

+1

Nur um es zu vervollständigen. Die Arrays sind Co-Varianten. Also sollte dieser Code gut funktionieren.\t \t Klasse Fruit {} \t \t Klasse Apfelfrucht {} \t \t Klasse Eltern { \t \t öffentlichen Obst [] getIT() { \t \t \t return null erstreckt; \t \t} \t \t} \t \t Klasse Child erstreckt Eltern { \t \t @Override // DIESE \t \t öffentlich von Apple [] getIT() ARBEITET { \t \t \t return null; \t \t} \t \t} – Veeram

+0

Sicher. Natürlich wird jeder Versuch, den Typ in der Array-Kovarianz zu verletzen, eine Ausnahme auslösen. Die Art der Array-Kovarianz wird zur Laufzeit erzwungen. –

0
class Fruit{} 
class Apple extends Fruit{} 

class Parent { 
    public Set<? extends Fruit> getIt(){ 
     return null; 
    } 
} 

class Child extends Parent { 
    @Override // THIS DOESN'T WORK 
    public Set<Apple> getIt(){ 
     return null; 
    } 
} 

sondern weil eine Klasse ist nicht eine Unterklasse von selbst seinem besseren Früchten machen eine andere Klasse zu Unterklasse (wie Superfrucht) und es in Ihren Eltern statt Obst verwendet getIt() Methode

+0

Diese Antwort könnte verbessert werden, indem Sie eine Erklärung hinzufügen, was Sie hier tun. –

+0

@ TobiasBrösamle nach diesem Schlüsselwort Ihr Rückgabetyp akzeptiert alles, was Ihre Klasse erweitert! Sie brauchen es, denn wenn Sie eine Methode überschreiben, können Sie den Rückgabetyp nicht ändern –

+0

Ich weiß, was ' 'bedeutet, aber ich denke, das OP nicht. Deshalb habe ich Sie gebeten, eine Erklärung dafür zu geben, was Ihr Code macht und wie er das Problem zu Ihrer Antwort löst. –

2

Die Der Rückgabetyp der überschreibenden Methode muss ein Untertyp des Rückgabetyps der überschriebenen Methode sein. Apple kann ein Untertyp von Fruit sein, aber Java-Generika sind in den Typparametern invariant, so dass dies nicht bedeutet, dass Set<Apple> ein Untertyp von Set<Fruit> ist.

Sonst könnte man Dinge tun, wie:

Parent p = new Child(); 
Set<Fruit> fruitSet = p.getIt(); // actually a Set<Apple> 
fruitSet.add(new Fruit());  // oops! 

Sie diese Grenzen durch die Verwendung Art beheben:

class Parent { 
    public Set<? extends Fruit> getIt() { 
     return null; 
    } 
} 

class Child extends Parent { 
    @Override 
    public Set<Apple> getIt(){ 
     return null; 
    } 
} 
Verwandte Themen