2011-02-04 12 views
2

これは暗黙の型変換の定義とまったく同じことではありませんが、私はこの標準でどのくらいの標準を打ち破っているのでしょうか...。Javaの暗黙のオブジェクト型ですか?

私は基本的に変数をキャストする抽象クラスを作成しますコンストラクタに渡される文字列によって異なります。例えば

:あなたは私が何を取得しています

public abstract class MyClass { 

    Object that; 

    public MyClass(String input){ 
     if("test1".equals(input){ 
      that = new Test1(); 
     } 
     else{ 
      that = new Test(); 
     } 
    } 

    public void doSomething(){ 
     if(that instanceof Test1){ 
      //specific test1 method or variable 
     } else if(that instanceof Test2)} 
      //specific test2 method or variable 
     } else { 
      //something horrible happened 
     } 
    } 
} 

参照してください?今私が遭遇する問題は、私のコンパイラがthatをまたはTest2doSomethingメソッドに明示的にキャストしてほしいということです。ifステートメントがかなり保証されているにもかかわらず、タイプ。

私が得意なのは、これは有効な解決策ですか?

私は他のクラスは基本的に同じことをしますが、単純な違いによって2つの異なるライブラリを使用します。このクラスは他のすべてのオブジェクトを簡単に追跡して変更するのに役立ちます。

+0

これは単なる恐ろしいデザインではありません(それは全体の列対行論争の議論です)。しかし、通常はタイプ間の多型性を奨励する「Javaモデル」*には適合しません。このタイプのアプローチは、「真の」多型(Cおよびタグ付きの共用体)がない言語やパターンマッチングをサポートする言語でよく見られます。 –

答えて

10

あなたは正しいです。これは設計において多形性を達成するための恐ろしい方法です。あなたは工場を使うことを考えましたか?戦略オブジェクト?あなたが達成しようとしているものが、これらのパターン(そしておそらく他のもの)の組み合わせを使ってより疎結合の方法で実装できるように思えます。例えばdoSomethingの多型について

、:

interface Thing { 
    public void doThing(); 
} 

class Test1 implements Thing { 
    public void doThing() { 
     // specific Test1 behavior 
    } 
} 

class Test2 implements Thing { 
    public void doThing() { 
     // specific Test2 behavior 
    } 
} 

class MyClass { 

    Thing _thing; 

    public void doSomething() { 
     _thing.doThing(); // a proper polymorphism will take care of the dispatch, 
          // effectively eliminating usage of `instanceof` 
    } 
} 

もちろん、あなたが共通のインターフェースのセットの下でTest1Test2(現在および計画やその他の具体的なThingクラス)の振る舞いを統一する必要があります(s)。

PS:このデザインは一般にStrategy Patternとして知られています。

+3

+1 ...とサンタ、このアドバイスは、シーズン外の贈り物と見なすことができますか? – Powerlord

+2

ホーホー!このサンタは一年中楽しそうです! – Santa

+0

@Santa、すばらしい答え...私はそれを選んで、私がそれを私の手段に使うことができるかどうかを判断しようとしています。私はできると思うが、確かめる前にそれを試さなければならないと思う:D – Shaded

1

別のクラスファイルを作成します。したがって、あなたは次のようなものを持っています: 1. "MyClass"抽象メソッド呼び出しdoSomethingを定義する "MyClass"内の "MyClass" - >これは、そのメソッドの特定の実装を強制的にそのサブクラスにします。 2. Test1は、doSomethingメソッドの実装を含むMyClassの実装になります。 3.チェックが "instanceOf"であるユーティリティクラスを作成します。このクラスは、別のクラスに属するコンストラクタには入れないでください。

最後に、抽象クラスと実装の3つのクラスファイルと、 "instanceOf"チェックを行うクラスがあります。私はこれが多くのように聞こえるが、あなたがやろうとしていると思うもののために、設計するための適切な方法だと思います。あなたはデザインパターンの本を手に入れなければなりません、私はそれがあなたにこれらのような質問をたくさんお手伝いすると思います。

+0

ところで、私はあなたに少なくともこの質問をすることを勧めます...あなたはこのような恐ろしいことをするプログラマーがいることに驚くでしょう。 –

+0

私はそれを疑うことはありません、私はいくつかのひどいコードを見たことがあります(そしておそらく学校でそれを少し書いたでしょう)。私が何かひどいことをするときはいつでも、私はこの残念な考えを持っています...もっと良い方法でなければなりません。それがSOが救助に来るところです! – Shaded

1

Open-Closed principleは、このクラス外でオブジェクトの作成を移動すると、より効果的です。

インターフェイスを実装するオブジェクトを受け入れるようにコンストラクタを変更することを検討してください。

public MyClass { 
    public MyClass(ITest tester) { m_tester = tester; } 
    public void doSomething(){ m_tester.doTest(); } 
} 

これは、コード(修正に閉鎖)を変更せずに(拡張に開放)クラスの動作を変更することができます。

1

これを行うより良い方法は、interfaceを作成して、オブジェクトで確実に呼び出すことができる一連のメソッドを指定することです。ここで

は例です:

public interface TestInterface 
{ 
    void doTest(); 
} 

今、あなたは、このインタフェースを実装するために、あなたのクラスを書くことができます。つまり、インタフェース内のすべてのメソッド(この場合はdoTest())の完全な定義を提供する必要があります。

public class Test implements TestInterface 
{ 
    public void doTest() 
    { 
    // do Test-specific stuff 
    } 
} 

public class Test1 implements TestInterface 
{ 
    public void doTest() 
    { 
    // do Test1-specific stuff 
    } 
} 

本当に退屈で無意味に見えますか?余分な仕事がたくさんある、私はあなたの言うことを聞いた。

真の値は、呼び出し元のコードに付属しています...

public abstract class MyObject 
{ 
    Test that; 

    // [...] 

    public void doSomething() 
    { 
    that.doTest(); 
    } 
} 

ないif文、ノーinstanceofは、ない醜いブロック、何もありません。これはすべて、共通インタフェースメソッド(ここでも doTest())でクラス定義に移動されます。

関連する問題