私は共分散と反分散について読んでいます-ウィキペディアは次のことについて話しています:
人を表すクラスがあるとします。人は医者に診てもらうことができるので、このクラスにはメソッド virtual void Person::see(Doctor d) があるかもしれません。ここで、Person クラスのサブクラスである Child を作成するとします。つまり、子は人です。次に、Doctor、Pediatrician のサブクラスを作成したいと思うかもしれません。子供が小児科医だけを受診する場合は、型システムでそれを強制したいと考えています。ただし、単純な実装は失敗します。Child は Person であるため、Child::see(d) は小児科医だけでなく、任意の医師を対象とする必要があります。
これが「単純な実装」です。
public interface IDoctor
{
}
public interface IPerson
{
void VisitDoctor(IDoctor doctor);
}
public class Adult : IPerson
{
public void VisitDoctor(IDoctor doctor)
{
Console.WriteLine("Adult saw doctor of type: {0}", doctor.GetType().Name);
}
}
public class Child : IPerson
{
public void VisitDoctor(IDoctor doctor)
{
Console.WriteLine("Child saw doctor of type: {0}", doctor.GetType().Name);
}
}
public class AdultDoctor : IDoctor
{
}
public class ChildDoctor : IDoctor
{
}
これらのテスト:
[Test]
public void AdultSeesDoctor()
{
var adult = new Adult();
adult.VisitDoctor(new AdultDoctor());
adult.VisitDoctor(new ChildDoctor()); // <-- Would like this to fail
}
[Test]
public void ChildSeesDoctor()
{
var child = new Child();
child.VisitDoctor(new AdultDoctor()); // <-- Would like this to fail
child.VisitDoctor(new ChildDoctor());
}
出力:
成人の医師の種類: AdultDoctor
成人の医師の種類: ChildDoctor
子供の医者のタイプ: AdultDoctor
子供はタイプの医師を見ました: ChildDoctor
これで、大人が子供の医者を訪ねようとした場合、または子供が大人の医者を訪ねようとした場合 ( をスローSystem.InvalidCastException
)、実行時エラーをスローする次のコードを実装できます。
public interface IVisitDoctors<T> where T : IDoctor
{
void VisitDoctor(T doctor);
}
public class Child : IPerson
{
private readonly ChildDoctorVisitor _cdv = new ChildDoctorVisitor();
public void VisitDoctor(IDoctor doctor)
{
_cdv.VisitDoctor((ChildDoctor)doctor);
}
}
public class Adult : IPerson
{
private readonly AdultDoctorVisitor _adv = new AdultDoctorVisitor();
public void VisitDoctor(IDoctor doctor)
{
_adv.VisitDoctor((AdultDoctor)doctor);
}
}
Adult
のクラスがタイプ の医師のみを訪問するAdultDoctor
ように強制できますか?タイプの医師が訪問された場合にコンパイル時エラーがスローされますChildDoctor
(クラス の場合はその逆Child
)。