C# のオブジェクトには、実際にはさまざまなカテゴリの複合体である関数が含まれる場合があります。これの古典的な例は教師の例です:
この例では、教師は個人の特徴 (目の色など) (ただし、この例を破る可能性のある教師が何人かいます) と従業員の特徴 (給与など) を持っています。
C# では多重継承が許可されていないため、代わりにインターフェイスを使用した構成のアイデアに注目しています。多くの場合、次のように説明されます。
継承とは、Cat が Animal から継承する場合、Cat は「動物」であることを意味します。
構成は、Cat が Noise を実装する場合、Cat が Noise を「持つ」ことを意味します。
この区別が重要なのはなぜですか。さて、私たちの猫を想像してみてください。実際には、Cat に Feline を継承させ、さらに Feline に Animal を継承させることができます。ある日、他のタイプのアニマルをサポートすることを決定したため、アニマルを改訂することにしましたが、その後、これらの変更を他のすべてのサブタイプにプッシュすることに気付きました。私たちの設計と階層は突然非常に複雑になり、最初からうまくいかなかった場合は、すべての子クラスを大幅に再設計する必要があります。
ルールはInheritanceよりも合成を優先することですが、優先という言葉の使用に注意してください。これは重要です。これは、単に合成を使用する必要があるという意味ではなく、継承が有用な場合と合成が有用な場合を設計で考慮する必要があるためです。それも。また、可能なすべてのメソッドを基本クラスに固執するのは悪い考えであることも思い出させてくれます。
あなたの形の例が好きです。検討:
ShapeSorter には、次のようなメソッドが含まれる場合があります。
public bool Sort(Shape shape)
{
foreach(Hole hole in Holes)
{
if(Hole.Type == HoleType.Circular && shape is Circle)
{
return true;
}
if(Hole.Type == HoleType.Square && shape is Square)
{
return true;
}
if(Hole.Type == HoleType.Triangular && shape is Triangle)
{
return true;
}
}
return false;
}
または、制御を少し反転させることもできます。
public bool Sort(Shape shape, Hole hole)
{
return hole.Accepts(shape); //We end up pushing the `if` code into Hole
}
またはその変形。私たちはすでに、Shape の正確な種類を知っていることに依存する多くのコードを書いています。次のいずれかがある場合、維持するのがどれほど面倒になるか想像してみてください。
その代わりに、私たちは自分自身で考えます - 問題を関連する特性に絞り込むことによって、問題を説明できるより一般的な方法はありますか?
あなたはそれをIShapeと呼んだ:
public interface IShape{
double Area {get;}
double Perimeter { get; } //Prefer Perimeter over circumference as more applicable to other shapes
int Sides { get; }
HoleType ShapeType { get; }
}
次に、Sort メソッドは次のようになります。
public Hole Sort(IShape shape)
{
foreach(Hole hole in Holes)
{
if(hole.HoleType == shape.ShapeType && hole.Area >= shape.Area)
{
return hole;
}
}
return null;
}
これは見た目はすっきりしていますが、Shape を介して直接行うことができなかったわけではありません。
真実は、真実がないということです。最も一般的なアプローチは、継承と構成の両方を使用することです。現実世界の多くのものは型であり、インターフェイスによって最もよく説明される他の属性も持っているためです。避けるべき最も重要なことは、可能なすべてのメソッドを基本クラスに固執し、派生型ができることとできないことを解決する巨大な if ステートメントを用意することです。これは、維持するのが難しい多くのコードです。また、基本クラスに多くの機能を配置すると、コードが具体的に設定される可能性があります。すべての潜在的な副作用のために、後で修正する必要はありません。