2017-07-07 15 views
2

私は同じクラスMasterObjectを拡張する2つのクラスObjectAObjectBを持っています。私はObjectAObjectBの両方を実装したいというメソッドを含むインターフェースも持っています。このメソッドはMasterObject内にありません。私はタイプMasterObjectのフィールドを持ち、メソッドObjectAObjectBにアクセスしたいクラスを持っています。キャストせずにこれは可能ですか?ここに私が持っているいくつかのコードがあります。Java継承 - 同じメソッドを使用する2つのクラス

さらに、MasterObjectクラスを変更することはできません。

public interface MyInterface{ 
    void doSomething(); 
} 

class ObjectA extends MasterObject implements MyInterface { 

    @Override 
    public void doSomething(){ 
     //... 
    } 
} 

class ObjectB extends MasterObject implements MyInterface { 
    @Override 
    public void doSomething(){ 
     //... 
    } 
} 

class Main { 
    MasterObject mObj; 

    public void method1() { 
     mObj = new ObjectA(); 
     mObj.doSomething(); 
    } 

    public void method2() { 
     mObj = new ObjectB(); 
     mObj.doSomething(); //runs code from ObjectB class 
    } 
} 

これは明らかにいくつかのコンパイラの問題を投げかけています。 (メソッドdoSomething()を解決できません)。

キャスティングのように:((ObjectA) mObj).doSomething();が動作しているようですが、キャストなしでこれを行う別の方法はありますか?何かクリーナー?

+0

'MasterObject'クラスを変更できますか? – CraigR8806

+0

@ CraigR8806いいえ、私はそうではありません。 –

答えて

2

クリーンな方法は、型としてのインターフェイスを持つオブジェクトを宣言することになります。

MyInterface mObj; 

あなたは同じように具体的なクラスとオブジェクトをインスタンス化することができます

mObj = new ObjectA(); 
... 
mObj = new ObjectB(); 

唯一の制約がありますキャストなしでは、doSomethingメソッドだけを呼び出すことができます。なぜなら、インターフェイスに定義されている唯一のメソッドだからです。この方法だけを使用するつもりなら、それは行く方法です。

+1

ありがとうございます。これは動作するようです。私はできるだけ私の問題を単純化しましたが、真実はいくつかの方法が共有されていて、私がインターフェースに追加する必要があるということです。 –

1

問題はクラスMasterObjectは、彼の子供たちが行うにもかかわらず、インターフェイスMyInterfaceを実装していません。

ソリューションは、インターフェイスを実装することです:

MyInterface mObj; 
mObj = new ObjectA(); 
3

一つの最終的な解決策は、MyInterfaceこれを実装するプロキシ抽象クラスAbstractMasterObjectを作成することです場合ObjectAObjectBMasterObjectMyInterfaceの両方の完全な機能を持つことができるようになります

:彼らはこれがそうのように行うことができます AbstractMasterObject

を拡張しますあなたはそのようなあなたのオブジェクトを宣言する可能性が10

は次に:

AbstractMasterObject a = new ObjectA(); 
AbstractMasterObject b = new ObjectB(); 
+0

プロキシはより良いアプローチです – emotionlessbananas

1

あなたはここにいくつかのオプションがあり、一部はすでに言及されています。あなたはすでにMasterObjectにインターフェイスを追加することはできませんし、相互作用はちょうどdoSomethingよりも複雑であると述べました。他のどのような制約も、あなたに最適なものを決定する可能性があります。

最初の選択肢は、クレイグが提案するようにして、MasterObjectを拡張してMyInterfaceを実装するために中間AbstractMasterObjectを作成することです。これは、MasterObjectMyInterfaceの両方のインスタンスを持つ単一の参照をすばやく簡単に作成できます。欠点は、MainMasterObjectの代わりにAbstractMasterObjectを使用しなければならないことです。だから、MasterObjectという他のサブクラスは使用できません。それはまったく問題ではないかもしれませんし、完全な契約者かもしれません。現実的には、それは間にある。

もう1つの選択肢は、継承の代わりに合成を使用することです。したがって、ObjectAObjectBはそれぞれ、拡張する代わりにMasterObjectのインスタンスを持ちます。そして、彼らは(簡潔にするために、私はちょうどObjectAを示しています)MasterClass行動へのアクセスのためにその参照を使用します。ここから

class ObjectA implements MyInterface { 

    private masterObject masterObject; 

    public ObjectA(MasterObject masterObject){ 
     this.masterObject = masterObject; 
    } 
    @Override 
    public void doSomething(){ /* Implementation */ } 

} 

Mainにこれを組み込むために、いくつかの異なる戦略があります。 MasterClassへの参照がMainにあり、それをObjectAコンストラクタに渡すことができます。その後、両方のMasterClassMyInterface参照を維持:ObjectAMasterObjectメソッドをオーバーライドすることも、いずれprotectedメンバにアクセスし、どちらも場合

​​

このアプローチは動作します。また、MainObjectAの両方に同じMasterObjectへの参照を持つ混乱につながる可能性があります。両方のクラスがMasterObjectの状態を変更することができれば、ややこしいバグに終わるかもしれません。一方、これらのどれもが心配しない場合、これは良い方法かもしれません。 MasterObjectを中断することなくMyInterfaceMainに追加し、MasterObjectを間接的に使用してMyInterfaceを実装します。

またはMasterObjectを完全にMainから非表示にして、MyInterfaceを介してのみやりとりすることができます。これを行うには、単にgetMasterObjectMyInterfaceにすることができます。または、具体的にはMainとのやりとりに関するメソッドをMyInterfaceに追加することもできます。このようなアプローチは最もクリーンだと思いますが、ほとんどのコードを変更する必要があります。これが主に新しい開発であれば、それはリファクタリングの努力に値するかもしれません。それが古いコードであれば、私はあまり侵略的ではない方法を好むでしょう。

もう1つの選択肢は、少し異なる方向からアプローチします。クラスは、定義したとおりに使用します。差がMainが同じインスタンスを指し両方MasterObjectMyInterface基準を有することである。

class Main { 

    private MasterObject masterObject; 
    private MyInterface myInterface; 

    public void method1(){ 

     ObjectA objectA = new ObjectA(); 
     masterObject = objectA; // Legal because ObjectA extends MasterObject 
     myInterface = objectA; // Legal because ObjectA implements MyInterface 

     myInterface.doSomething(); // This does ObjectA's implementation 
     masterObject.someMasterObjectMethod(); 

    } 
} 

Mainするように、同じインスタンスがMyInterfaceMasterObjectとして実行することを完全に偶然です。私は、これが最も侵襲的でないため、これがレガシーコードであれば、このアプローチが最も良いと思います。これが比較的新しいコードなら、私はこのようなものに頼る前に他の戦略を検討したいと思います。まだ他のアプローチがありますが、これは良い概観であるべきだと思います。何があっても、元に戻って、それぞれのクラス間の関係が本当に何であるかを考えなければなりません。それはあなたを正しい方向に向けるのに役立ちます。

関連する問題