2017-02-08 4 views
1

タイプセーフな方法で何かのIDを表すために作成したJavaの汎用インターフェースがあります。これは基本的に次のように見えます。ジェネリックタイプを継承階層で2回実装する

public interface ID<T extends BaseOfAllIDNeedingObjects> { 
    long getId(); 
    boolean isConcrete(); 
} 

これは正確ではありませんが、デモンストレーションの目的には十分です。実際のID番号は取得できますが、IDをインスタンス化するためのさまざまなラッピング機能があります。そのため、IDが表すオブジェクトがあるかどうか、またはオブジェクトにキャストしたい場合はラッパーを確認できます。これは単一のオブジェクトにはうまくいくが、少なくともいくつかのオブジェクトが他のオブジェクトを継承するという問題があり、特定のタイプに対して基本タイプを使用するケースがある。したがって、たとえば:

public class SpecificThing extends BaseThing { 
    /* stuff */ 
} 

public class BaseThing extends BaseOfAllIDNeedingObjects { 
    /* stuff that all Things need */ 
} 

自然に、私は異なる状況でBaseThingとSpecificThingの両方のIDを表すことができるようにしたいと思います。 SpecificThingを取得するには、データベース内の異なるテーブルからデータを取り出すために余分な作業が必要になるため、時には必要なすべての情報が含まれているためBaseThingが必要な場合もあります。ただし、Javaでは次のことが許可されていません。

public class BaseThing extends BaseOfAllIDNeedingObjects implements ID<BaseThing> { 
    /* base thing stuff here */ 
} 

public class SpecificThing extends BaseThing implements ID<SpecificThing> { 
    /* specific things */ 
} 

これはまっすぐなコンパイラエラーです。私のIDE(Jetbrains)では、「IDは異なる型引数 'BaseThing'と 'SpecificThing'で継承することはできません。私はこれを回避できる方法はありますか? BaseThingにIDをタグ付けする必要はありません.SpecificThingsをIDとして使用してBaseThingsを別のIDオブジェクトにラップすることしかできませんか?それとも、私はこのような何かを私に働かせてくれるかどうかわからないいくつかのパターンがありますか?

+0

基本的には、現在のコードベースは、BaseThing、SpecificThing、またはその他のTotallyUnrelatedThingなど、さまざまなオブジェクトを表す多数の「long someId」パラメータを渡します。これらのパラメータを型安全で自己文書化する( "name + type of id"以上)ようにして、オブジェクトの具体的なインスタンスをラッパーの代わりに渡して、長いメモリ割り当てを保存する。編集:そして、私たちはメモリにオブジェクトをプルしたくないだけでなく、IDがほしいと思う時間がたくさんあります。長時間がSQLに直接渡されるからです。 – Freezerburn

答えて

3

あなたは抽象クラスまでBaseThingの実装を引いた後、自己再帰的な一般的なパラメータを使用することができます。

public abstract class AbstractBaseThing<T extends AbstractBaseThing<T>> extends BaseOfAllIDNeedingObjects implements ID<T> { 
    /* base thing stuff here */ 
} 

public class BaseThing extends AbstractBaseThing<BaseThing> { 
    /* concrete base thing */ 
} 

public class SpecificThing extends AbstractBaseThing<SpecificThing> { 
    /* specific things */ 
} 
0

あなたはこのようにクラスを定義することができます。

public class BaseThingGeneric<T extends BaseThingGeneric<T>> extends BaseOfAllIDNeedingObjects implements ID<T> { 
    /* base thing stuff here */ 
} 

public class BaseThing extends BaseThingGeneric<BaseThing> { 
    /* just redefine the constructors */ 
} 

public class SpecificThingGeneric<T extends SpecificThingGeneric<T>> extends BaseThingGeneric<T> { 
    /* specific things */ 
} 

public class SpecificThing extends SpecificThingGeneric<SpecificThing> { 
    /* just redefine the constructors */ 
} 

実装がされますBaseThingGenericとSpecificThingGenericにある必要があります。 BaseThingとSpecificThingは、インスタンス化をセミプライベート化するためだけに用意されています。 さらに、ScecificThingは、SpecificThingGenericを拡張することによって同様に拡張可能です。

関連する問題