0

形状クラスを設計したい。いくつかの異なる形状を区別する必要があります。

-Point  
-Line  
-Triangle  
-Circle  
-Polygons  

このクラスの主な目的は、2 つの図形間の距離を計算することです。
これらの距離を計算するためのすべての方法がありますが、使用できる単一の方法が必要です。次のようになります。

float Distance(Shape a, Shape b)

それを行う最も簡単な方法は、多くの if ステートメントを配置してから適切なメソッドを呼び出すことですが、これは間違いなく OOP ではありません。

そのようなクラスを OOP スタイルで設計するにはどうすればよいですか?

4

6 に答える 6

3

最も近い点を使用して 2 つのオブジェクト間の距離を計算するメソッドを実装している場合、両方のオブジェクトの型を知る必要があるため、これは難しい問題です。たとえば中心点を使用して比較する場合は簡単です。GetCenterメソッドを追加するだけですが、この場合はうまくいきません。

問題は、クラス階層を拡張可能に設計できる場合 (つまり、既存の型を変更せずに他の型を追加できる場合) にクラス階層が役立つことです。追加するときに、 などEllipseを実装する必要があるため、これはここでは当てはまりません...関数型言語で知られている代数データ型を使用してこれを表現する方がはるかに簡単です。たとえば、F# では次のようになります。DistancePointEllipseDistanceTriangleEllipse

type Shape = 
  | Circle of float * float * float // center & radius
  | Point of float * float          // center

次に、パターン マッチングを使用して、考えられるすべてのケースを処理できます。

match shape1, shape2 with
| Circle(x1, y1, r1), Circle(x2, y2, r2) -> // two circles
| Point(x1, y1), Point(x2, y2) -> // two points
| Circle(cx, cy, r), Point(px, py) 
| Point(px, py), Circle(cx, cy, r) ->
    // point and a circle (both combinations

関数型プログラミングは、この問題により適しているようです:-)。

とにかく、可能な(ただしまだ非拡張の)オブジェクト指向設計の 1 つは、現在のタイプから他のタイプの形状までの距離を計算するメソッド、などをShape含む基本クラスを持つことです(すべての組み合わせが本当に必要なため)。 .DistanceToPointDistanceToTriangle

別のアプローチは、オーバーロードされたメソッドを C# で単純に記述することです。

float Distance(Triangle t, Point p);
float Distance(Triangle t, Circle c);
// ... etc

このオプションの良い点は、作成する必要があるメソッドの数を簡単に減らすことができることです。Ellipseたとえば、とのケースがある場合、Pointを継承CircleしてEllipse、 と比較するときに既存のケースを使用するCircleこともできPointます。

于 2010-04-10T20:00:55.620 に答える
1

これを拡張可能にする設計の 1 つは、特定の形状で動作する戦略として距離測定をカプセル化することです。新しい Shape タイプのペアのデリゲートを登録すると、システムはこれを使用して、シェイプ タイプの任意のペアに対して適切な関数を解決できます。これにより拡張性が可能になりますが、複雑さが増し、パフォーマンスが低下します。説明したように階層が単純である場合、単純な条件はより高速で維持しやすくなります。

ここでの本当の問題は、問題の関数が特定のクラスの単純な動作ではなく、システム内のすべての形状に関する知識を必要とすることです。「OOP」に対してできる最善の方法は、すべてのシェイプを認識しているマネージャー クラスにすべての面倒な条件をカプセル化することです。この機能を提供した結果として導入される必要な結合を避けることはできませんが、説明したように、少なくともより単純なインターフェイスの背後に隠すことができます。

于 2010-04-10T20:39:09.243 に答える
1

何を「距離」と定義するかによって異なります。基本クラスに、各派生クラスによってオーバーライドされる抽象 CenterPoint プロパティを与えることができます。今は簡単です。

于 2010-04-10T19:16:59.323 に答える
0

形状をポリゴンに変換するflattenメソッドを使用して抽象Shape基本クラスを作成します。

abstract class Shape
{
    virtual Polygons Flatten();
}

2つのポリゴン間の距離を計算するコードは十分に簡単なはずです。次に、Distance関数は次のようになります。

float Distance(Shape a, Shape b)
{
    Polygons polygonsA = a.Flatten();
    Polygons polygonsB = b.Flatten();
    return polygonsA.Distance(polygonsB);
}
于 2010-07-14T15:12:02.127 に答える
0

形状がすべて X 軸と Y 軸の両方で対称であり、中心から距離を計算する必要があるPoint GetCenter()場合は、抽象基本クラスにメソッドが必要です。そこから、距離の式を使用してそれらの間の距離を計算します。

于 2010-04-10T19:17:20.817 に答える
0

Shapeこれらの各図形のクラスを継承する抽象基本クラスを作成できます。基本クラスでは、必要な機能 ( など) の抽象メソッドを宣言しますがCalculateDistance、コードはありません (つまり、bodyはありません)。継承された各クラスで、このメソッドの実装を提供する必要があります。

Shape関連する注意事項:ある形状派生クラスから別の形状派生クラスにかなりの量のコードをコピーする必要があるような方法で、クラスのプロパティとメソッドを選択します。その場合は、そのコードを抽象Shapeクラスのプロパティまたはメソッドに配置する必要があります。最終的に、各サブクラスには、形状ごとに異なる部分のコードのみが含まれます。これは、実装によって、形状を内部的に表現する方法によって異なります。

于 2010-04-10T19:17:24.517 に答える