假设以下课程:
public class Animal
{
}
public class Dog : Animal
{
public void Bark()
{
}
}
public class Cat : Animal
{
public void Meow()
{
}
}
Animal cat = Cat();
Animal dog = Dog();
PatternIamLookingFor.DoSomething(cat); // -> Call Meow
PatternIamLookingFor.DoSomething(dog); // -> Call Bark
这可能吗?没有像MakeNoise()这样的方法添加到Animal基类?
在我的应用程序中,我有一个CatFactory和一个DogFactory,它实现AnimalFactory并返回Animals。我不能在工厂打电话给喵/树皮,我收到动物后就不能打电话了。
答案 0 :(得分:2)
这可能吗?没有像MakeNoise()这样的方法添加到Animal基类?
不使用反射,动态或其他基于运行时的方法搜索方法来调用。基于经典多态的方法是在MakeNoise()
类中使用通用方法(如Animal
)。
答案 1 :(得分:2)
在您的示例代码中,Animal
上没有多态的行为 - 也就是说,与基类的引用相同的消息会导致执行不同的具体行为。
答案 2 :(得分:2)
你可以通过一个界面来实现,这与你的Animal.MakeNoise()
差不多,但有点不同。
public class Animal
{
}
public interface IAnimalNoises
{
void MakeNoise();
}
public class Dog : Animal, IAnimalNoises
{
IAnimalNoises.MakeNoise()
{
Bark();
}
public void Bark()
{
}
}
public class Cat : Animal, IAnimalNoises
{
IAnimalNoises.MakeNoise()
{
Meow();
}
public void Meow()
{
}
}
public class PatternIamLookingFor
{
public static void DoSomething(IAnimalNoises animal)
{
animal.MakeNoise();
}
}
Animal cat = new Cat();
Animal dog = new Dog();
PatternIamLookingFor.DoSomething(cat); // -> Call Meow
PatternIamLookingFor.DoSomething(dog); // -> Call Bark
Cat cat2 = new Cat();
cat2.MakeNoise(); //Compiler error as it is not visible unless cast as a IAnimalNoises
如果您正在使用无法更改的旧代码,这可能是您的最佳选择,但是如果您有选项,我强烈建议您重构代码并在每个孩子中调用MakeNoise()
类,并让基类(或接口)定义它。
答案 3 :(得分:2)
我可以想到几种方法可以实现上述内容。
如果您可以修改原始源代码,这可能是最佳选择。易于实施,易于维护。
public interface IDoSomething
{
void DoSomething();
}
public class Dog : Animal, IDoSomething
{
public void Bark()
{
}
void IDoSomething.DoSomething(){
Bark();
}
}
public class Cat : Animal, IDoSomething
{
public void Meow()
{
}
void IDoSomething.DoSomething(){
Meow();
}
}
如果您无权访问原始源代码,则适配器可能是唯一选项。您可以使用它们来“同步”代码访问Cat和Dog类的方式。您仍然可以使用适配器,就像它是原始对象一样,但使用更好地适应新代码需求的修改过的接口。创建工厂以基于父类型创建适当的适配器会非常简单。
public IDoSomething
{
void DoSomething()
{
}
}
public DoSomethingFactory
{
public static IDoSomething( Animal parent )
{
if ( typeof( parent ) is Dog )
return new DoSomethingDog( parent as Dog );
if ( typeof( parent ) is Cat )
return new DoSomethingCat( parent as Cat );
return null;
}
}
public DoSomethingDog : Dog, IDoSomething
{
Dog _parent;
public DoSomethingDog( Dog parent )
{
_parent = parent;
}
public void DoSomething()
{
_parent.Bark();
}
}
public DoSomethingCat : Cat, IDoSomething
{
Cat _parent;
public DoSomethingCat( Cat parent )
{
_parent = parent;
}
public void DoSomething()
{
_parent.Meow();
}
}
除了这两个明显的实现之外,您可能还需要考虑这些:
使用Decorators动态增强类的功能。 (类似于上面的“包装”方法,但更干净地融入了类结构。)
实现您的类可以动态处理的一系列Command个对象:
cat.Do( new MakeNoiseCommand() ); // Handled as "meow"
dog.Do( new MakeNoiseCommand() ); // Handled as "bark"
允许类似于Mediator的内容根据Animal的类型等转发请求:
public class AnimalMediator
{
public void MakeNoise( Animal animal )
{
if ( typeof( animal ) is Dog ) (animal as Dog).Bark();
else if ( typeof( animal ) is Cat ) (animal as Cat).Meow();
}
}
答案 4 :(得分:0)
如果您创建了一个包含void MakeNoise()然后在不同动物类型上实现接口的Called IActions接口,那么它将更具扩展性。
覆盖每只动物使用方法的方式。然后只需调用方法...... 实施例
public class Dog : Animal, IActions //Just import the Interface here
{
//Interface for Makenoise
public void MakeNoise()
{
//Its implementation... Make this different for each animal
}
}