2013-04-29 23 views
7

これは不可能だと感じていますが、そうでないと非常に便利です。親クラスをJavaにキャストできるようにクラスを拡張する

私は、子クラスが新しいメソッド、新しいコンストラクタ、新しいフィールドを持たないように親クラスを拡張しようとしています。そのため、子クラスの基礎となるデータ構造は親クラスと同じです。これは、組み込みのJavaクラス(たとえばVector3d)に追加された関数を追加する場合に発生する傾向があります。基礎となるデータが同一で​​あるとすれば、親クラスとして初期化されたオブジェクトを子クラスにダウンキャストすることが可能です。追加された機能を使用できます。私が何を意味するかの例では、新しいメソッドを使用する

import javax.vecmath.Vector3d; 

public class Vector3dPlus extends Vector3d{ 
    //same fields, same constructors as Vector3d 

    public double extraMethod(){ 
     return x+y+z; 
    } 
} 

てみてください下に見るように、通常我々がVector3dPlusメソッドが動作することを保証することはできませんので、明らかにJavaはこれに動揺します

import javax.vecmath.Vector3d;  

public class Test { 

    public static void main(String[] args) { 
     Vector3d basic=new Vector3d(1,2,3); 

     useExtraMethod(basic); //this line correctly raises an exception, but is there a way around that 
    } 

    public static void useExtraMethod(Vector3dPlus plus){ 
     System.out.println(plus.extraMethod()); 
    } 
} 

をするVector3Dに追加すべてVector3dです。しかし、とにかく私は基本的なデータ構造が同じであるので、すべてのダウンキャストをすべてVector3dからVector3dPlusに許可すると言うことができます。

私はこれに対処する現在の方法は、一般的なユーティリティクラス内のすべての余分なメソッドを置くことですが、それは明らかに恐ろしいビットだ

+0

「Vector3dPlus」の代わりに「Vector3d」を作成する理由はありますか?そうでなければ: 'Vector3dPlus {super(int a、int b、int c); } ' – Aquillo

+2

私はインタフェースを使用します – chrisw

+1

最初にVector3dPlusとして初期化しない理由は、ライブラリを作成していて、従来のクラスを外部的に使用したいが、内部的に追加された関数を使用できるようにするためです。 –

答えて

4

あなたはメソッドのオーバーロードとコピーコンストラクタでそれを達成することができます:

public class Vector3dPlus extends Vector3d { 
    public Vector3dPlus(Vector3d vector) { 
     super(...); // parameters from vector 
    } 

    // rest of your Vector3dPlus code 
} 

とあなたのテストクラスでは、メソッドをオーバーロード:

public class Test { 

     public static void useExtraMethod(Vector3d vector) { 
      useExtraMethod(new Vector3dPlus(vector)); 
     } 

     public static void useExtraMethod(Vector3dPlus plus){ 
      System.out.println(plus.extraMethod()); 
     } 

     public static void main(String[] args) { 
      Vector3d basic=new Vector3d(1,2,3); 
      useExtraMethod(basic); // this line works now 
     } 
    } 
+0

コピーコンストラクタに関連付けられた余分なガベージコレクションを避けたいと思っていましたが、私はそれをやらなければならないと感じていました –

+0

@Richtea:Javaでは 'BaseClass'オブジェクトを' SubClass'にキャストできません。また、プロファイラを実行して本当にそれがわからない限り、ガベージコレクションがボトルネックとなることは想定しないでください。 – jlordo

+0

十分なことですが、それは少し特殊なケースです。もし私がBaseClassをコントロールしていれば、それを行う理由はありません。 –

2

私はクラス階層が、より多くの基礎となるデータ構造に焦点を当てていないでしょう露出している外部インターフェイスに表示します。

Vector3DPlusクラスには、Vector3Dに追加のメソッドがありません。これは、そのインタフェースを基底クラスと区別して、完全に代替できないようにします。コンパイラは、基本型がサブ型を予期するメソッドに渡されたときに、例外を正しく発生させます。

私は、あなたが希望する動作を達成するために何らかの形式のチェックを避けることができるとは思いません。何らかの理由で、Vector3DPlusのインスタンスだけがメソッドに渡されるようにする必要があります。それがダウンキャスティングの価格です。

public static void main(String[] args) { 
     Vector3d basic=new Vector3d(1,2,3); 

     if(basic instanceof Vector3dPlus){ 
     useExtraMethod(basic); //this line correctly raises an exception, but is there a way around that 
     } 
} 
0

これはいかがですか?

import javax.vecmath.Vector3d; 

public class Vector3dPlus extends Vector3d{ 
    Vector3dPlus { 
     super(int a, int b, int c); 
    } 

    public double extraMethod(){ 
     return x+y+z; 
    } 
} 

と、次のように使用します。

import javax.vecmath.Vector3d; 

public class Test { 

    public static void main(String[] args) { 
     Vector3d basic=new Vector3d(1,2,3); 
     Vector3dPlus plus=new Vector3dPlus(1,2,3); 

     useExtraMethod(basic); 
     useExtraMethod(plus); 
    } 

    public static void useExtraMethod(Vector3d vector){ 
     if (vector instanceof Vector3dPlus) { 
      System.out.println(((Vector3dPlus) vector).extraMethod()); 
     } 
    } 
} 
0

これを実現できます以下に説明するように[あなたはそれのinstanceof使用したいいけない場合は、これを達成するための他の方法がないです]:

public class Test { 

    public static void main(String[] args) { 
     Vector3dPlus basicPlus = new Vector3dPlus(1,2,3); 
     Vector3d basic=basicPlus; 

     useExtraMethod(basic); 
    } 

    public static void useExtraMethod(Vector3dPlus plus){ 
     System.out.println(plus.extraMethod()); 
    } 
} 

Javaは型キャストをチェックするための内部機構を有しています。 「子クラスは型の親クラスです」ではなく、「親クラスは子クラスではありません」という基本的な基本をバイパスすることはできません。

関連する問題