2010-12-22 81 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) { ... } 

等等。