2009-05-11 8 views
1

不変クラスがあります。汎用リターン

Idは、その型のオブジェクトを返すのが好きです。たとえば、

timerange.crop(scope) 

は、スコープではなくTimerangeオブジェクトを返す必要があります。

すべてのメソッドをオーバーライドする必要がありますか(またはリフレクションを使用する必要がありますか)。 これを行う別の方法はありますか?

ありがとうございます。 Etam。

+0

最高の結果を得るには、 'Cmp extends Comparable <? extends Cmp> ' – newacct

答えて

4

何らかの工場が必要です。この場合、ファクトリメソッドは正常に動作します。

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 (...); 
    } 
} 

あなたは、基本クラスにジェネリック「この」パラメータを追加することもできます。これは、クライアントコードに余分な作業を追加しない

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 (...); 
    } 
} 

2

Javaにはセルフタイプのリターンがないため、通常はすべてのメソッドを手動でオーバーライドする必要があります。可能な選択肢についての説明は、my blog on "self types"を参照してください。

2

次の操作を試みることができる:

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

TIMERANGEオブジェクトを返しますTIMERANGEが

class TimeRange extends Scope<Date, Timerange> 

のでcropとして定義されます。派生クラスが未定義の場合、汎用ワイルドカード(Scope<Date, ?>)を使用できます。

+0

しかし、ジェネリック型のオブジェクトを作成する方法はありません。 – newacct

+0

抽象クリエータメソッドを実装する必要があります。 – Dario

0

本当にTimerangeが必要ですか? Scope<Date>以上のものは何ですか?そうでない場合は、Scope<Date>を使用してください。

もう1つの提案は、コンストラクタを使用してインスタンス化するのではなく、オブジェクトを複製して、新しいオブジェクトのフィールドを適切に変更することです。理由は、複製されたオブジェクトが元のオブジェクトと同じ型であるためです。

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; 
}