。オブジェクト指向言語、またはオブジェクト指向の概念を実装できるC++言語のように、これは通常Visitorパターンを使用して解決されます。
Visitor
インターフェイス自体は、コンクリートタイプごとに1つのコールバックを一般的に定義します。
class Circle;
class Rectangle;
class Square;
class Visitor {
public:
virtual void visit(Circle const& c) = 0;
virtual void visit(Rectangle const& r) = 0;
virtual void visit(Square const& s) = 0;
};
次に、Shape
階層がこれに適合します。 2つの方法が必要です。いずれかのタイプのビジターを受け入れる方法と、もう1つは、「適切な」交差ビジターを作成する方法です。
class Visitor;
class Intersecter;
class Shape {
public:
virtual void accept(Visitor&) const = 0; // generic
virtual Intersecter* intersecter() const = 0;
};
intersecterは単純です:
#include "project/Visitor.hpp"
class Intersecter: public Visitor {
public:
Intersecter(): result(false) {}
bool result;
};
例えば、サークルのためにそれを与える:
#include "project/Intersecter.hpp"
#include "project/Shape.hpp"
class Circle;
class CircleIntersecter: public Intersecter {
public:
explicit CircleIntersecter(Circle const& c): _left(c) {}
virtual void visit(Circle const& c); // left is Circle, right is Circle
virtual void visit(Rectangle const& r); // left is Circle, right is Rectangle
virtual void visit(Square const& s); // left is Circle, right is Square
private:
Circle const& _left;
}; // class CircleIntersecter
class Circle: public Shape {
public:
virtual void accept(Visitor& v) const { v.visit(*this); }
virtual CircleIntersecter* intersecter() const {
return new CircleIntersecter(*this);
}
};
と使用方法:
#include "project/Intersecter.hpp"
#include "project/Shape.hpp"
bool intersects(Shape const& left, Shape const& right) {
boost::scope_ptr<Intersecter> intersecter(left.intersecter());
right.accept(*intersecter);
return intersecter->result;
};
他の方法が必要な場合に二重ディスパッチ機構、次にa結果をラップし、Visitor
から継承し、派生クラスによってオーバーライドされたShape
に根ざす新しい「ファクトリ」メソッドが適切な操作を提供するように、別の「仲介者のような」クラスを作成する必要があります。少し長めですが、うまくいきます。
注:intersect(circle, rectangle)
とintersect(rectangle, circle)
を除いて同じ結果が得られることは妥当です。コードを因数分解することができ、具体的な実装にはCircleIntersecter::visit
代理人がいます。これにより、コードの重複が回避されます。
これはダブルディスパッチによって解決される古典的な問題です。 – Mankarse
私の元々の検索は二重ディスパッチで現れたことはありませんでしたが、私はそれが自分の問題をどのように解決するかを見ています。ありがとう。編集:私はそれをアップ投票するが、私は十分な評判を持っていないかどうかわからない、または私はちょうど投票ボタンを見つけることができません。 –