2013-12-17 8 views
5

Nehmen wir an, ich habe die Standard Draw-Klasse mit geerbten Klassen von Circle und Square. Gibt es eine Möglichkeit, folgendes zu tun? Vielleicht mit Generika?Kann eine Java-Methode, die eine Basisklassenmethode implementiert, eine geerbte Klasse zurückgeben?

class Draw { 
    public abstract Draw duplicate(); 
} 

class Circle extends Draw { 
    public Circle duplicate() { 
    return new Circle(); 
    } 
} 

class Square extends Draw { 
    public Square duplicate() { 
    return new Square(); 
    } 
} 
+0

Draw sollte eine abstrakte Klasse sein. Sonst sieht es gut aus – k2col

Antwort

4

Ja, es ist möglich, dass eine überschreibende Methode einen Typ zurückgibt, der eine Unterklasse des Rückgabetyps der Superklassenmethode ist. Diese Technik, die "kovariante Rückgabetypen" genannt wird, ist at the bottom of a Java tutorial on return types beschrieben. Dies funktioniert, weil ein Circle und ein SquareDraw s sind, also selbst wenn Sie eine Oberklasse-Referenz haben, und Sie nicht wissen, oder welche Unterklasse Sie wirklich haben, erhalten Sie immer noch eine Draw zurück.

Übrigens, um Ihren Code zu kompilieren, müssen Sie nur die Draw Klasse abstract machen. Alles andere, einschließlich der kovarianten Rückgabetypen, sieht gut aus.

+0

Oh wow, das ist super einfach. Das ist die Kehrseite, für immer in Java zu sein, du weißt nicht, wann diese neuen Dinge passieren. Vielen Dank. –

4

Ja, Sie können seit Java 5.

Seit Java 5, eine Methode in einer Unterklasse eine Unterklasse des Typs ein Objekt, dessen Typ zurückgeben kann durch das Verfahren mit der gleichen Signatur in der zurück Oberklasse. (source). Dies wird als kovariante Rückgabetypen bezeichnet.

1

würde ich Generika verwenden hier:

class Draw<T> { 
    public abstract T duplicate(); 
} 

class Circle extends Draw<Circle> { 
    @Override 
    public Circle duplicate() { 
    return new Circle(); 
    } 
} 

class Square extends Draw<Square> { 
    @Override 
    public Square duplicate() { 
    return new Square(); 
    } 
} 
+0

Hey Alex, kannst du erklären, warum du Generika verwenden würdest? Es scheint überflüssig. – bcorso

+0

Sie können nicht sicher Dienstprogrammmethoden auf der Grundlage der Oberklasse ohne Generika schreiben ... –

+0

So etwas wie 'public static > T duplizieren (T zeichnen) {return draw.duplicate(); } ' –

1

Ich denke, was Sie Folgendes tun möchten, ist: auf T

public abstract class Draw<T extends Draw> { 
    public abstract T duplicate(); 
} 

public class Circle extends Draw<Circle> { 
    @Override 
    public Circle duplicate() { 
     return new Circle(); 
    } 
} 

public class Square extends Draw<Square> { 
    @Override 
    public Square duplicate() { 
     return new Square(); 
    } 
} 
  1. Verwendung der Generika (mit Einschränkung, sollte diese erweitern Draw, um seltsame Vererbung wie Circle extends Draw<List> zu vermeiden)
  2. Fügen Sie abstract Stichwort zu die Draw Klasse

Dann können Sie folgendes tun:

Square originalSquare = new Square(); 
Circle originalCircle = new Circle(); 

Square duplicatedSquare = originalSquare.duplicate(); 
Circle duplicatedCircle = originalCircle.duplicate(); 

EDIT

Ohne die Generika, Sie so etwas wie dies tun könnte:

public abstract class Draw { 
    public abstract Draw duplicate(); 
} 

public class Circle extends Draw { 
    @Override 
    public Circle duplicate() { 
     return new Circle(); 
    } 
} 

public class Square extends Draw { 
    @Override 
    public Square duplicate() { 
     return new Square(); 
    } 
} 

Dank Pavel, Rgettman und Enno Shioji wusste ich nichts von "kovariant return type".

+0

Haben Sie tatsächlich die anderen Antworten gelesen? Sie können tun, was Sie beschreiben, ohne Generika zu verwenden. –

+0

Ich hatte die andere Antwort nicht gesehen, bevor ich meine eigene Antwort geschrieben hatte. Ich wusste nicht über kovariante Rückgabetypen, danke. – ssssteffff

Verwandte Themen