2011-09-23 243 views
2

我可以這樣做嗎? (過於簡單化了,因爲它太複雜)C# - 繼承,覆蓋

abstract class A { 
    public string Print() {} 

    public static string DoPrint(A a, Type T) { 
    ((T)a).Print(); // <-- This should call eg. A3.Print(), not A.Print() 
    } 
} 

class A1: A { 
    public new string Print() {} 
} 

class A2: A { 

} 

class A3: A { 
    public new string Print() {} 
} 

class Somewhere 
{ 
    A3 a3 = new A3(); 
    a3.DoPrint(); 
} 

我有很多類(A1,A2,A3等),其從基類繼承(A)

我試圖創建上面的A類中的DoPrint()函數。 可以這樣做嗎?

我想這

public static string DoPrint(A a) { 
    a.Print(); 
    } 

但它調用A.Print(),而不是A3.Print()

編輯: 「傳遞一個類型作爲參數」 改了稱呼從因爲每個人都是對的,我可以使用虛擬(謝謝!)。這個問題在別的地方撒了謊,與這個問題無關。

+1

爲什麼你在'A1'等''Print'方法聲明中指定'new'關鍵字?如果是關閉編譯器警告,請將它們取出並考慮警告給出的建議。 –

+0

你不需要傳遞類型。只需使Print方法在所有類中都是虛擬的並且可以工作。 –

+4

爲什麼不讓'Print'成爲'virtual'方法?這就是'虛擬'的意義所在。 – Jon

回答

1

有什麼不對正常的虛擬方法和繼承?看看使用虛擬和覆蓋:

abstract class A { 
public virtual string Print() {} 

    public static string DoPrint(A a) { 
    a.Print(); // <-- This WILL call eg. A3.Print(), not A.Print() 
    } 
} 

class A1 : A 
{ 
    public override string Print() {} 
} 

class A2 : A 
{ 
    public override string Print() {} 
} 
class A3 : A 
{ 
    public override string Print() {} 
} 
+0

對不起。並非所有類都需要重寫Print()。你在這種情況下做什麼? – Aximili

+0

如果不是所有類都需要重寫Print,那麼只需要在需要它的類中重寫它,並在基類中提供基本實現。仍然沒有理由不使用繼承與我現在的信息... – jeroenh

1

基本上沒有。你不能。除非你進入反思層面,並通過它找到並調用T定義的Print方法。任何類似接口或dynamic的應用程序都會選擇最上面的實現。

但是,我不知道是否Print()這裏應該是virtual

abstract class A { 
    public abstract string Print(); 
} 

class A1: A { 
    public override string Print() {} 
} 

class A2: A { 
    public override string Print() {} 
} 

class A3: A { 
    public override string Print() {} 
} 

並調用a.Print();。然後多態性將稱爲Print()的最衍生覆蓋。

+0

對不起,並不是所有的類都會覆蓋Print()。編輯的問題。這整個事情確實在各地都在使用Reflection。那麼你如何「通過該方法調用T上定義的Print方法」呢?在這種情況下,最頂級的意味着A? – Aximili

3
public static string DoPrint(A a) { 
    a.Print(); 
} 

會工作,但您需要聲明打印爲虛擬並覆蓋它。

abstract class A { 
     public virtual string Print() {} 

     public static string DoPrint(A a) { 
      a.Print(); 
     } 
    } 

    class A1: A { 
     public override string Print() {} 
    } 

    class A2: A { 
     public override string Print() {} 
    } 

    class A3: A { 
     public override string Print() {} 
    } 

    class Somewhere 
    { 
     A3 a3 = new A3(); 
     A.DoPrint(a3); 
    } 
+0

對不起,我只是意識到並不是所有的類都會覆蓋Print()函數。這就是爲什麼它不是虛擬的。 – Aximili

+1

如果所有類都是虛擬的,則不需要覆蓋它。 –

2

代替使用new,將基類的Print方法標記爲虛擬,然後在子類方法聲明中使用覆蓋。

public virtual string Print() { } 

而在子類:

public override string Print() { } 
+0

對不起,我很粗心。並不是所有的類都會覆蓋Print()。這就是爲什麼它不是虛擬的。 – Aximili

+2

@aximili - 並非所有課程都必須覆蓋「打印」。一旦方法被標記爲虛擬的,它是一個*可選的*覆蓋。任何不會覆蓋Print的類將使用由抽象樹中的虛擬或上次覆蓋提供的基線。 –

1

DoPrint()是一個靜態函數。

你應該這樣調用它:

A3.DoPrint(a3, typeof(A3));

A3.DoPrint(a3, a3.GetType());

現在,我不爲什麼你想這樣做明白。爲什麼不簡單地在類A中虛擬Print()並在派生類中重寫它?