2013-05-19 8 views
5

私は、これは前に頼まれている必要があります確信しているが、私は同様の例を見つけるように見えることはできません。私はよく多型とメソッドのオーバーロードを理解しますが、ここで私をエスケープ溶液で一見単純なシナリオです:多型のようなパラメータの処理 - 単純なOO?

だが、私はいくつかの派生クラスで基本クラスを持っているとしましょう。私は、この例

base Shape 
derived Circle extends Shape 
derived LineSeg extends Shape 

などのための形状を使用します

今、形状はというメソッドを持って交差する(他の)彼らが交差する場合、別の形状に対してテストを参照すること。多型を使えば、サークル、LineSegなどは、自分の「交差」のメソッドを実装することができ、そして、メソッドのオーバーロードで、私は簡単に必要なすべての組み合わせを実装することができます。どのように見ることは容易です例えば、

Circle.intersect(LineSeg) 
Circle.intersect(Circle) 
LineSeg.intersect(Circle) 

など

これまでのところは良いです。

問題は、私は形状の中央リストを続けるならば、私はこれをしたい、次のとおりです。

for some shape s 
Foreach shape in Shapes 
    if (s.intersect(shape)) - do something 

メソッドのオーバーロードは、「交差」を選択するので、現在、私は、これが可能であるかを確認していませんメソッドを使用して、適切なパラメータ型ではなく、基本型Shapeに一致させます。タイプとダウンキャストをチェックするif-elseチェインなしでこれを行うにはどうすればよいですか?

ところで、私は、Javaを使用していますが、私は基本的な設計の問題であると思われるので、言語は全く関連性があることを確認していません。とてもシンプルに見えますが、私は何が欠けていますか?

ありがとうございます!


解決済み(ありがとうございました!)、詳細はこちらをご覧ください。それは必要な適切な型を持っているとして、基本的には、(ビジターパターン?)適切なメソッドを呼び出す派生クラスでのコールバックを持つことによって、あなたは、適切なintersectメソッドを呼び出すために、「この」キーワードを使用することができます。

+1

と呼ばれています。たとえば、LISPは* multimethods *をサポートしていますが、関数型プログラミング言語のいくつかは同じものをサポートしていると思います。 Javaでは、これは通常* double dispatch *と呼ばれ、GoF Visitorパターンは移動方法です。 –

+1

あなたのデザインを忠告しないでください。あなたの継承は少し間違っています。線分は実際には形状ではありません。彼らは形を作ります。問題の2つの図形を構成した線分、形に応じて、多くのいずれかの交差点をチェックします:) – ChiefTwoPencils

+0

@ C.Lang、良いキャッチですが、 "wall"に改名するとどうなりますか?それは基本的にどのように使用されていますが、それをlineSegと呼ぶと、他のより複雑な図形でも簡単に使用できます。 – user1922401

答えて

3

私の最初の考えはビジターパターンであり、すべてのシェイプに2つのメソッドを与えました.1つはintersect(Shape)と呼び、1つのシェイプタイプはdoIntersect()です。

それはこのよう程度になります。

interface Shape { 
    public abstract Intersection intersect(Shape other); 

    public abstract Intersection doIntersect(Circle circle); 

    public abstract Intersection doIntersect(LineSeg line); 
} 
class LineSeg implements Shape { 
    @Override 
    public Intersection intersect(Shape other) { 
     return other.doIntersect(this); 
    } 

    Intersection doIntersect(Circle circle) { 
     // Code to intersect with Circle 
    } 

    Intersection doIntersect(LineSeg other) { 
     // Code to intersect with another Lineseg 
    } 
} 

class Circle implements Shape { 
    @Override 
    public Intersection intersect(Shape other) { 
     return other.doIntersect(this); 
    } 

    public Intersection doIntersect(Circle other) { 
     // Code to intersect with another Circle 
    } 

    public Intersection doIntersect(LineSeg segment) { 
     // Code to intersect with LineSeg 
    } 
} 

あなたはdoIntersect方法がプライベートパッケージまたはしかしこれらは異なる名前を選んだことをお勧めします。シェイプ<内の各形状を参照してくださいジェネリックJDK5

+0

これは素晴らしいです、ありがとう。私の問題をすばやく簡単に修正しました。私はすべてのパラメータ型の可能性を基本クラスのプロトタイプとして追加する必要があります。 – user1922401

+0

もう1つの改良点:特定のものを 'doIntersect()'と命名する代わりに、 'intersect()'メソッドにすべて名前を付けることができます。私が知る限り、コンパイラは最初に適合する最も特定のオーバーロードを選択します。 – confusopoly

+0

ありがとう - 私はすでにそれをしましたが、あまり混乱しないかもしれないので、あなたの提案を残すことに決めました。私も基本クラスに入れてみましたが、1つしか必要ありませんでしたが、ベースクラスのメソッドで "this"を使用すると、残念なことにベースクラスの型がありました。(理由は分かります) – user1922401

0

>

0

あなた形状クラスは、それが、唯一の派生クラスサークルをインスタンス化するために取得しないとインスタンスを持つlineseg意味、抽象クラスでなければなりません。 intersectメソッドは、すべての形の上にそうするときに、ループ形状で仮想である必要があり、各形状の交差方法は、いくつかのプログラミング言語は、より直接的に引数の実行時型にオーバーロードをサポートし

public abstract class Shape { 

    boolean intersect(Shape s); 
} 

public class Circle extends Shape { 

    boolean intersect(Shape s) { 
     ... 
     if(s instanceOf Circle) { 
      .... // Circle intersects cicrcle 
     } else if(s instanceOf Lineseg) { 
      .... // Circle intersects Lneseg 
     } else { 
      throw RuntimeException("Unrecognized shape"); 
     } 

    } 

} 

public class Lineseg extends Shape { 

    boolean intersect(Shape s) { 
     ... 
     if(s instanceOf Circle) { 
      .... // Lineseg intersects circle 
     } else if(s instanceOf Lineseg) { 
      .... // Lineseg intersects lineseg 
     } else { 
      throw RuntimeException("Unrecognized shape"); 
     } 
    } 

} 
+0

申し訳ありませんが、そのif-else型チェックチェーン – user1922401

+0

@ user1922401しかし、派生クラスのそれぞれに、派生クラスごとにメソッドを書きたいと思っています。このようにして、古典的なオブジェクト指向の多態性を扱う方法があります。 – ilomambo

+0

それは同じではありません、ビジターパターンを介して1つの余分な間接指示があります。 if-elseチェインを使用すると、メソッドを呼び出すたびに最悪のn個のチェックが発生します。さらに、提案された解決策はわずかに安全である。新しい型を追加すると、新しい型付けされた交差するヘッダーを基本クラスに追加する必要があります。そうしないと、コンパイルされず、他のすべての型が強制的に処理されます。あなたは各クラスにif-elseを持たせることを提案していますが、これは一元化することができます – user1922401

関連する問題