我认为OOP中有一些基本的东西:
环境:C#/。net 2.0
假设我有两节课:
public class Animal
{
}
public class Dog : Animal
{
}
具有两种方法的服务类:
public void DoStuff(Animal animal)
{
Console.Write("Animal stuff");
}
public void DoStuff(Dog animal)
{
Console.Write("Dog stuff");
}
如果我执行以下代码:
Animal instance = new Animal();
MyService.DoStuff(instance);
Animal instance2 = new Dog();
MyService.DoStuff(instance2);
“动物的东西”被打印两次。
所以我的问题是:为什么?如何在不转换instance2的情况下获取“Animal stuff”和“Dog stuff”,或者将方法从我的服务移动到我的类(事实上我希望我的代码可以工作,但不是:()
由于
PS:这些只是示例:)
因为访客模式并不吸引人,所以我只是将我的服务方法移到我的班级,等待更好的解决方案。
答案 0 :(得分:1)
您没有覆盖Dog中的doStuff()方法,因为参数类型不同。它们是两种不同的方法。
更改Dog中的签名以匹配Animal或创建一个为您排序的访问者。
这是编写它的一种方法:
public interface Animal { void accept(AnimalVisitor visitor); }
public class AbstractAnimal : Animal
{
public void accept(AnimalVisitor visitor) { visitor.visit(this); }
}
public class Dog : AbstractAnimal {}
public class Cat : AbstractAnimal {}
public interface AnimalVisitor
{
void visit(Animal animal);
void visit(Dog dog);
void visit(Cat cat);
}
现在服务(以及所有其他服务)可以实现AnimalVisitor并对每个Animal子类型执行不同的操作。
这是一种称为“双重调度”的常见模式;你可以在Scott Meyers的“更有效的C ++”中阅读更多相关内容。
答案 1 :(得分:1)
原因是第二次召唤虽然经过了一只狗,却将参考传递给动物。该引用可以是任何类型的动物(您恰好已经通过了Dog)但.NET不知道所以它必须调用接受对Animal的引用的方法的版本而不是更具体的引用。
答案 2 :(得分:1)
另一件似乎是黑客攻击的事情是将传递的参数强制转换为dynamic
。这将允许您实现“动态访问者”,例如,您可以编写
foreach (dynamic a in animals)
doStuff(a);
void doStuff(Animal a) { ... }
void doStuff(Dog d) { ... }
等等。