2010-12-22 80 views
0

它,我觉得事端基本在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,或从我的服务移动方法到我的班级(其实我希望我的代码有效,但它不是:()

谢谢

PS:这些只是例子:)


因为访问者模式是不是真的有吸引力,我只是将我的服务的方法上我的课,等待更好的解决方案。

回答

1

您不重写Dog中的doStuff()方法,因为参数类型不同。他们是两种不同的方法。

要么改变Dog中的签名以匹配动物,要么创建一个Visitor来为您排序。

下面就来写一个方法:

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和做不同的事情,每个动物亚型。

这是一种常见的叫做“double dispatch”的模式;您可以在Scott Meyers的“更有效的C++”中阅读更多内容。

+0

doStuff不是狗或动物课的一部分,你能解释一下游客吗? – 2010-12-23 08:22:37

+0

我刚刚阅读了更多关于这种模式的内容,实际上它似乎是一种解决方案,但它有一些默认设置:1 /它需要很多代码才能实现,2我们失去了服务类的好处:我们有办法它在动物课上的方法,3 /如果你不知道这种模式,你不知道发生了什么! – 2010-12-23 09:02:54

1

原因是第二个电话虽然通过了狗,但却将参考号传递给动物。该引用可以是任何类型的动物(你只是碰巧通过了一条狗),但.NET不知道,因此它必须调用接受引用动物的方法版本,而不是更具体的引用。

1

另一件看似破解的事情是将传递的参数转换为dynamic。这会让你实现一个'动态访问者',例如你会写

foreach (dynamic a in animals) 
    doStuff(a); 

void doStuff(Animal a) { ... } 
void doStuff(Dog d) { ... } 

等等。