使用组合而不是继承:
不是基于消化系统进行继承,而是将消化分解为自己的一组类。
首先,一个描述不同饮食方式的界面。
public interface IDigest
{
void Eat(Meat food);
void Eat(Plant food);
void Eat(Offal food); //lol nethack
}
肉食动物吃肉,有时可以吃药草,不喜欢废话:
public class Carnivorous : IDigest
{
public void Eat(Meat food)
{
Console.Write("NOM NOM");
}
public void Eat(Plant food)
{
if(Starving)
Console.Write("Ugh, better than nothing.");
else
Vomit();
}
public void Eat(Offal food)
{
Vomit();
}
}
草食动物很挑剔,宁愿死也不吃肉(我知道,保存你的评论,这是一个例子)
public class Herbivorous : IDigest
{
public void Eat(Meat food)
{
Vomit();
}
public void Eat(Plant food)
{
Console.Write("NOM NOM");
}
public void Eat(Offal food)
{
Vomit();
}
}
杂食动物什么都吃。见证州博览会。
public class Omnivorous : IDigest
{
public void Eat(Meat food)
{
Console.Write("NOM NOM");
}
public void Eat(Plant food)
{
Console.Write("NOM NOM");
}
public void Eat(Offal food)
{
Console.Write("NOM NOM");
}
}
所有动物都必须吃东西,所以它们必须有消化系统以及其他系统。
public abstract class Animal
{
/* lots of other stuff */
public IConsume DigestiveSystem {get;set;}
/* lots of other stuff */
}
嬉皮士是具有已知口味的动物类别。它在实例化时自行配置。也可以从外部注入行为和系统。
public class Hippie : Animal
{
public Hippie()
{
/*stuff*/
DigestiveSystem = new Herbivore();
BodyOdorSystem = new Patchouli();
/*more stuff*/
}
}
最后,让我们看看嬉皮士吃汉堡。
public static void Main()
{
Hippie dippie = new Hippie();
Meat burger = new Meat("Burger", 2/*lb*/);
dippie.DigestiveSystem.Eat(burger);
}
在对像动物这样的复杂系统进行建模时,我更喜欢组合而不是任何时候的继承。复杂的系统可以快速爆炸继承树。以三种动物系统为例:杂食/草食/肉食、水/空气/陆地和夜间/昼夜。我们甚至不用担心如何决定哪个分类成为 Animals 的第一个区分点。我们是先将 Animal 扩展到 Carnivore,先到 WaterLiving,还是先到 Nocturnal?
由于杂食动物可以生活在空中并喜欢夜晚(蝙蝠*),并且还可以是白天行走的陆地生物(人类),因此您必须有一条能够满足每一个选择的继承路径。那是一个已经有 54 种不同类型的继承树(它很早,善良)。动物比这复杂得多。您可以轻松获得具有数百万种类型的继承树。绝对是组合优于继承。
*例如,新西兰短尾蝙蝠是杂食性的。