2011-03-12 61 views
0

我正在設置一個測試組件,並試圖保持它的通用性。我想使用一個通用的Visitor類,但不確定使用後代類。在C中使用子訪問者#

實施例:

public interface Interface_Test_Case 
{ 
    void execute(); 
    void accept(Interface_Test_Visitor v); 
} 


public interface Interface_Test_Visitor 
{ 
    void visit(Interface_Test_Case tc); 
} 


public interface Interface_Read_Test_Case 
    : Interface_Test_Case 
{ 
    uint read_value(); 
} 


public class USB_Read_Test 
    : Interface_Read_Test_Case 
{ 
    void execute() 
    { Console.WriteLine("Executing USB Read Test Case."); } 

    void accept(Interface_Test_Visitor v) 
    { Console.WriteLine("Accepting visitor."); } 

    uint read_value() 
    { 
    Console.WriteLine("Reading value from USB"); 
    return 0; 
    } 
} 


public class USB_Read_Visitor 
    : Interface_Test_Visitor 
{ 
    void visit(Interface_Test_Case tc) 
    { Console.WriteLine("Not supported Test Case."); } 

    void visit(Interface_Read_Test_Case rtc) 
    { Console.WriteLine("Not supported Read Test Case."); } 

    void visit(USB_Read_Test urt) 
    { Console.WriteLine("Yay, visiting USB Read Test case."); } 
} 

// Code fragment 
    USB_Read_Test test_case; 
    USB_Read_Visitor visitor; 
    test_case.accept(visitor); 

哪些C#編譯器使用,以確定哪些在USB_Read_Visitor的方法將由該代碼片段執行的規則?

我想分解我的測試組件的依賴關係。不幸的是,我目前的Visitor類包含visit方法,用於與測試組件無關的類。我是否想要實現不可能的目標?

+0

「代碼片段」根本不引起USB_Read_Visitor的任何成員的調用。 USB_Read_Test.accept()對其參數沒有任何作用。 – Odrade 2011-03-12 00:23:25

+0

我很想標題更改爲與「方法解析順序」再投,收爲是重複的東西[方法解析順序(http://stackoverflow.com/questions/2164960/method-resolution-order) 。除了用它作爲例子之外,這與訪問者模式沒有多大關係。 – 2011-03-12 01:18:23

+0

@Jeff M:我試圖實現一個通用測試用例的訪問者設計模式。測試用例的容器Test_Suite將*應用*訪問者到每個測試用例。經典的訪客設計模式將包括每種測試用例的「訪問」方法。這意味着測試經理必須參考所有測試用例。耦合變得非常緊密,這與我試圖達到的目的相反。 – 2011-03-12 06:14:30

回答

1

由於您的accept()方法實際上沒有調用任何visit()方法,所以沒有。 :)

不過,如果你調用它爲:

void accept(Interface_Test_Visitor v) 
{ 
    Console.WriteLine("Accepting visitor."); 
    v.Visit(this); // lets invoke it this time 
} 

編譯器會看到this首先是作爲USB_Read_Test一個實例,然後Interface_Read_Test_Case,然後Interface_Test_Case。它會首先選擇最直接的過載(或者可以使用隱式轉換的過載),然後沿着繼承鏈繼續下去,直到找到適合過載的合適類型。所以在這種情況下,它會調用visit(USB_Read_Test)。然而,如果你的類實現多個接口,每個接口都有過載卻是沒有的類,你會得到你將不得不解決多義性錯誤

v.Visit((Interface_Read_Test_Case)this); // argument is an instance of Interface_Read_Test_Case 
v.Visit((Interface_Test_Case)this);  // argument is an instance of Interface_Test_Case 

:您可以通過鑄造覆蓋此行爲。

例如,

interface IX { } 
interface IY { } 
class Class : IX, IY { } 

void Call(IX _) { } 
void Call(IY _) { } 
// no Call(Class _) method 

var c = new Class(); 
Call(c); // error: ambiguous call 
Call((IX)c); // not ambiguous 

有關詳細信息,請參閱Method resolution order並稍微相關C#: Passing null to overloaded method - which method is called?

0

正如評論所說,接受並沒有調用任何訪問方法,所以我回答基於我認爲你的意思... 我會認爲它基於作爲參數傳入的對象的聲明類型?

USB_Read_Test obj1 = new USB_Read_Test(); 
Interface_Read_Test_Case obj2 = new USB_Read_Test(); 

既作爲參數應導致visit(USB_Read_Test urt)爲OBJ1調用,和visit(Interface_Read_Test_Case rtc)爲OBJ2。

1

而是定義一個完整的接口和相關實現訪問的,定義一個接受一個行動訪問方法(或謂語或FUNC。這取決於你想要的觀衆做什麼)。

class TestCase 
{ 
    public void Visit(Action<T> action, T val) 
    { 
     action(val); 
    } 

} 

var tc = new TestCase(); 
uint some_val = 3; 
tc.Visit((Action) (val) => Console.WriteLine("Val " + val)); 

雖然我不完全清楚你想要做什麼,但定義一個採用Function的方法可以消除定義所有這些接口的必要性。