2009-10-19 74 views
1

我有以下代碼:多態性(不)與C#訪問者模式(和新的,而不是覆蓋)破

class Visitor 
{ 
    internal virtual void Visit(Node n) { } 
} 

class VisitorSpecial : Visitor 
{ 
    internal new void Visit(Node n) { } 
} 

class Base 
{ 
    internal virtual void Accept(Visitor v) { } 
    internal virtual void Accept(VisitorSpecial v) { } 
} 

class Node : Base 
{ 
    internal override void Accept(Visitor v){ v.Visit(this); } 
    internal override void Accept(VisitorSpecial v){ v.Visit(this); } 
} 

有爲什麼會調用 new Node().Accept(new VisitorSpecial())時,可以選擇 Accept(Visitor v) 方法的任何原因

更新:好的,我的壞,我意識到我在訪客中使用「新」,而不是覆蓋。現在我知道爲什麼「新中斷多態」。這使我的問題完全愚蠢。謝謝您的幫助。

+0

嗯。我只手頭有一個Mono C#編譯器,但在我的盒子上選擇了正確的Accept(VisitorApecial v)。 – 2009-10-19 10:23:12

+0

不應該將C#標記添加到您的問題嗎? – xtofl 2009-10-19 10:55:47

回答

2

我想你問的問題爲特定語言(C#? )。選擇最合適的重載(注意:不重寫!)由語言決定。這取決於它使用的功能查找類型:靜態(編譯時)或動態(運行時)。

如果你的語言使用靜態綁定,它可能會選擇最具體的呼叫,在這種情況下,n.Accept(new VisitorSpecial())將調用第二個過載。但是,

Visitor v = new VisitorSpecial(); 
n.Accept(v); 

將被靜態綁定到Node::Accept(Visitor)函數。

如果語言使用動態綁定,它可以根據參數的實際運行時類型選擇被調用函數。

在一般情況下,你可以變通的問題完全不使用過載,這僅僅是語法糖:使AcceptVisitorAcceptSpecialVisitor之間的區別。也添加一個AcceptManagerAcceptJustSimplyMy

4

不知道爲什麼它會被選擇(它可以從字面上是因爲它是第一個在類聲明和提供的參數匹配),但

Accept(VisitorSpecial v) 

功能是在這種情況下毫無意義,似乎是直至誤解多態。請嘗試以下明白爲什麼:

class Visitor 
{ 
    internal virtual void Visit(Node n) { Console.WriteLine("In normal visitor"); } 
} 

class VisitorSpecial : Visitor 
{ 
    internal override void Visit(Node n) { Console.WriteLine("In special visitor"); } 
} 

class Base 
{ 
    internal virtual void Accept(Visitor v) { } 
} 

class Node : Base 
{ 
    internal override void Accept(Visitor v){ v.Visit(this); } 
} 

上述內容,調用

someNode.Accept(new VisitorSpecial()); 

時會產生輸出

> In special visitor