2009-05-11 19 views
1

gibt es eine unveränderlich Klasse:Generisches Rückkehr

Scope<Cmp extends Comparable<Cmp>> 
public Scope<Cmp> crop(Scope<Cmp> scope) { 
    ... 
    return new Scope<Cmp>(starts, ends); 
} 

hat viele ähnliche Methoden erweitert:

Timerange extends Scope<Date> 

und viele andere (auch unveränderlich).

Id mögen sie, um Objekt seines Typs zurückzugeben. Zum Beispiel:

timerange.crop(scope) 

sollte TimeRange Objekt, nicht Scope zurückgeben.

Muss ich jede Methode überschreiben (oder Reflektion verwenden)? Gibt es eine andere Möglichkeit, dies zu tun?

Vielen Dank im Voraus, Etam.

+0

für die besten Ergebnisse verwenden 'Cmp erstreckt sich vergleichbar ' – newacct

Antwort

4

Sie benötigen eine Art von Fabrik. In diesem Fall funktioniert die Factory-Methode einwandfrei.

public abstract class Scope<E extends Comparable<E>> { 
    abstract Scope<E> create(E start, E end); 

    public Scope<E> crop(Scope<E> scope) { 
     ... 
     return create(starts, ends); 
    } 
} 
public TimeRange extends Scope<Date> { 
    Scope<Date> create(Date start, Date end) { 
     return new TimeRange (...); 
    } 
} 

Sie können einen generischen ‚dieses‘ Parameter auf die Basisklasse hinzuzufügen:

public abstract class Scope<THIS extends Scope<THIS, E>, E extend Comparable<E>> { 
    abstract THIS create(E start, E end); 

    public THIS crop(Scope<E> scope) { 
     ... 
     return create(starts, ends); 
    } 
} 
public TimeRange extends Scope<TimeRange,Date> { 
    TimeRange create(Date start, Date end) { 
     return new TimeRange (...); 
    } 
} 

Diese zusätzliche Arbeit an den Client-Code hinzufügt.

2

Java verfügt nicht über Rückgabetypen, daher müssen Sie im Allgemeinen jede Methode manuell überschreiben. Eine Diskussion mit einigen möglichen Alternativen finden Sie unter my blog on "self types".

2

könnten Sie versuchen, die folgenden:

class Scope<Cpm extends Comparable<Cpm>, Derived extends Scope<Cpm, Derived>> { 
    public Derived crop(Scope<Cmp, Derived> scope) 
} 

Timerange als

definiert werden würde
class TimeRange extends Scope<Date, Timerange> 

und so würde crop ein Timerange-Objekt zurück. Wenn die abgeleitete Klasse nicht definiert ist, können Sie generische Platzhalter verwenden (Scope<Date, ?>)

+0

Aber es gibt keine Möglichkeit, ein Objekt eines generischen Typs zu erstellen. – newacct

+0

Dann muss eine abstrakte Creator-Methode implementiert werden. – Dario

0

Benötigen Sie wirklich Timerange? Bietet es mehr als nur Scope<Date>? Wenn nicht, dann verwenden Sie einfach Scope<Date>.

Ein anderer Vorschlag ist, dass Sie das Objekt möglicherweise klonen können, anstatt es mithilfe des Konstruktors zu instanziieren, und die Felder dann entsprechend für das neue Objekt ändern. Der Grund dafür ist, dass das geklonte Objekt vom selben Typ wie das Original ist.

Scope<Cmp extends Comparable<Cmp>> implements Cloneable 
public Scope<Cmp> crop(Scope<Cmp> scope) { 
    ... 
    Scope<Cmp> result = (Scope<Cmp>)super.clone(); 
    result.init(starts, ends); // sets the fields for a cloned object 
           // init() could be private 
    return result; 
}