现在我有一种两难的境地。有一个类结构类似于以下类:
public interface IMammal
{
void Eat();
}
public interface IBarking
{
void Bark();
}
有IBarking
和IMammal
的情况。从理论上讲,我们的动物可以是其中之一,也可以只是其中之一。您可以看到Cow
IMammal
,Dog
是IMammal
和IBarking
。从理论上讲,我们甚至可以有人可以吠叫,但不是哺乳动物。
public class Mammal : IMammal
{
public void Eat()
{
Console.Write("Om-nom-nom");
}
}
public class Cow : Mammal
{
}
public class Dog : Mammal, IBarking
{
public void Bark()
{
Console.Write("Bark-bark!!!");
}
}
这是Farm
,只有一只动物生活在其中:
public class Farm
{
private readonly IMammal _animal;
public Farm(IMammal animal)
{
_animal = animal;
}
public void Feed()
{
_animal.Eat();
}
public void Guard()
{
var dog = _animal as IBarking;
if (dog != null)
dog.Bark();
}
}
我在这里看到的问题是,我们假设IBarking
总是IMammal
。这个设计有什么问题,如何解决?
答案 0 :(得分:3)
这些简化的例子几乎没有任何意义。您错过了"问题案例"那你想做什么显示一个实现IBarking
但不是IMammal
的类,以及将其传递给Farm
时出现的问题。无论如何,考虑到前提:
IMammal
存在。IBarking
存在。IBarking
的班级不 来实施IMammal
。Farm
必须接受IBarking
和 IMammal
。IMammal
。在这种情况下,您需要一个新的构造函数,一个新的私有成员和更多代码来在两者之间进行选择,或者需要重叠的接口。我跟随后者:IFarmable
。
然后你需要:
public interface IMammal : IFarmable
public interface IBarking : IFarmable
public Farm(IFarmable farmable) { ... }
很可能你有其他约束,比如"但是我想在传递给构造函数" 的变量上调用Eat()
,但是然后你的描述( >"我们认为IBarking
总是IMammal
" )不正确或不完整,您需要将Eat()
移至IFarmable
接口。
答案 1 :(得分:1)
我会尝试解释您的 意图 。
更好的设计是:
public class Farm
{
private readonly IMammal[] _animals;
public Farm(IMammal[] animals)
{
_animals = animals;
}
public void Feed()
{
foreach (var animal in _animals)
animal.Eat();
}
public IBarking GuardingAnimal { get; set; }
public void Guard()
{
if (GuardingAnimal != null)
GuardingAnimal .Bark();
}
}
您设计的变化:
我想要做出这种区分的原因是大多数动物都是被动的(你喂它们并且收获它们),而保护动物有一个特定的用例,因此不应该隐藏在其他动物中。
如果你想喂狗,你应该让那个界面继承IMammal
(除非你在哺乳动物中引入更多功能,在这种情况下你应该提取IFeedable
或类似)。