뿐만 아니라 기술로서 다음 콤바인 몇 가지 다른 답변의 가장 좋은 측면 중 일부의 핵심 요소 수 있도록 Cat
성기를 갖는 Excrement
요구의 자산 RadioactivePoo
유형을하지만 단지로 그것을 반환 할 수있는 Poo
우리가 가지고 한 우리 만 알고있는 경우가 AnimalBase
아닌 특히 Cat
.
호출자는 제네릭이 구현에 존재하더라도 제네릭을 사용할 필요가 없으며 특별한 .NET을 얻기 위해 다른 이름의 함수를 호출 할 필요가 없습니다 Poo
.
중간 클래스 AnimalWithSpecialisations
는 Excrement
속성 을 봉인하는 역할 만하며 public이 아닌 속성을 통해 파생 반환 형식 의 속성 이있는 SpecialPoo
파생 클래스에 연결합니다 .AnimalWithSpecialPoo<TPoo>
Excrement
경우 Cat
그의 유일한 동물이다 Poo
어떤 방법으로 특별이, 또는 우리의 유형이 원하지 않는 Excrement
a의 주요 정의 기능으로 Cat
, 중간 제네릭 클래스는 계층 구조에서 제외 될 수 그래서 Cat
직접 도출에서 AnimalWithSpecialisations
,하지만 경우가 누구의 주요 특징들이 있다는 것입니다 여러 가지 동물 Poo
의 중간 클래스에 "상용구"을 분리, 어떤 방법으로 특별하다 유지하는 데 도움이 Cat
별도의 가상 함수 호출의 몇 가지의 비용이기는하지만, 상당히 깨끗한 클래스 자체는.
예제 코드는 대부분의 예상 작업이 "예상대로"작동 함을 보여줍니다.
public interface IExcretePoo<out TPoo>
where TPoo : Poo
{
TPoo Excrement { get; }
}
public class Poo
{ }
public class RadioactivePoo : Poo
{ }
public class AnimalBase : IExcretePoo<Poo>
{
public virtual Poo Excrement { get { return new Poo(); } }
}
public class Dog : AnimalBase
{
}
public abstract class AnimalWithSpecialisations : AnimalBase
{
public sealed override Poo Excrement { get { return SpecialPoo; } }
protected virtual Poo SpecialPoo { get { return base.Excrement; } }
}
public abstract class AnimalWithSpecialPoo<TPoo> : AnimalWithSpecialisations, IExcretePoo<TPoo>
where TPoo : Poo
{
sealed protected override Poo SpecialPoo { get { return Excrement; } }
public new abstract TPoo Excrement { get; }
}
public class Cat : AnimalWithSpecialPoo<RadioactivePoo>
{
public override RadioactivePoo Excrement { get { return new RadioactivePoo(); } }
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
Poo dogPoo = dog.Excrement;
Cat cat = new Cat();
RadioactivePoo catPoo = cat.Excrement;
AnimalBase animal = cat;
Poo animalPoo = catPoo;
animalPoo = animal.Excrement;
AnimalWithSpecialPoo<RadioactivePoo> radioactivePooingAnimal = cat;
RadioactivePoo radioactivePoo = radioactivePooingAnimal.Excrement;
IExcretePoo<Poo> pooExcreter = cat;
IExcretePoo<RadioactivePoo> radioactivePooExcreter = cat;
animal = dog;
animalPoo = dogPoo;
pooExcreter = dog;
}