2011-11-30 74 views
21

我試圖刷新我的記憶,但找不到Google的答案。將派生類轉換爲基類

public class BaseClass 
{ 
    public virtual void DoSomething() 
    { 
     Trace.Write("base class"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public override void DoSomething() 
    { 
     Trace.Write("derived class"); 
    } 
} 

如果我創建派生類的實例,我怎麼把它轉換到它的基類,所以當DoSomething的()被調用時,它僅使用基類的方法?

一個動態轉換仍然調用派生類的重載方法:

DerivedClass dc = new DerivedClass(); 

dc.DoSomething(); 

(dc as BaseClass).DoSomething(); 

輸出:「派生類」

+1

失敗的一種傳承的目的,通常在您的覆蓋,雖然你會手動調用'base.DoSomething( )'但是除非你可以用反思做點什麼。 –

+0

哎喲,我認爲這會是我忽略的一些事情。謝謝 – Levitikon

+0

[如何調用(非虛擬)虛擬方法的原始實現?](http://stackoverflow.com/questions/3378010/how-to-invoke-non-virtually-the-original-implementation -of-a-virtual-method) – Ani

回答

29

你不能 - 這完全是故意的,因爲這就是多態的全部。假設你有一個派生類,它對傳遞給重寫方法的參數強加了某些先決條件,以保持完整性......你不希望能夠繞過驗證並破壞其內部完整性。

在課程本身中,您幾乎可以不虛擬地調用base.AnyMethod()(不管這是您的優先還是不重要),但沒關係,因爲這是課程本身決定可能會違反它的完整性 - 可能它知道它是什麼這樣做。

+0

謝謝喬恩。我想說清楚,我非常喜歡並依賴派生類的屬性和方法,即使在類被轉換爲基類時也是如此。在某些特殊條件下剝離派生類也是非常好的。它看起來像反思或某種深層複製是一條路。 – Levitikon

+0

我們確定這是正確的答案嗎?看起來你可以調用基本方法,如果派生類使用new關鍵字而不是重寫基類的虛擬成員。 – winnicki

+0

@winnicki:在這個問題上,情況並非如此。你可以調用基類方法,如果你根本沒有派生類方法,或者如果它有不同的名字,或者不同的參數等等...... –

3

嘗試使用new keywor而不是override據我所知,這應該啓用所需的行爲。 我並不確定,所以如果我錯了,請不要責怪我!

public class BaseClass 
{ 
    public virtual void DoSomething() 
    { 
     Trace.Write("base class"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public new void DoSomething() 
    { 
     Trace.Write("derived class"); 
    } 
} 
7

你絕對能(調用基方法),只是閱讀了關於多態性:

http://msdn.microsoft.com/en-us/library/ms173152(v=VS.80).aspx

例子:

public class BaseClass 
{ 
    public void DoWork() { } 
    public int WorkField; 
    public int WorkProperty 
    { 
     get { return 0; } 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public new void DoWork() { } 
    public new int WorkField; 
    public new int WorkProperty 
    { 
     get { return 0; } 
    } 
} 

以及如何調用它:

DerivedClass B = new DerivedClass(); 
B.DoWork(); // This calls the new method. 

BaseClass A = (BaseClass)B; 
A.DoWork(); // This calls the old method. 
+0

嗨,我在你的生產線上的視覺工作室中出現錯誤 –

21

雖然這聽起來不合理的,但它的工作原理

DerivedClass B = new DerivedClass(); 

BaseClass bc = JsonConvert.DeserializeObject<BaseClass>(JsonConvert.SerializeObject(B)); 
+2

深層複製是可接受的解決方案之一,但它的性能成本。 – Levitikon

+1

這將在序列化到基類時將派生類中可能存在的額外屬性放在哪裏?例如。 StudentDerived類在從StudentBase繼承時引入了學生身高。 – Vaibhav

+1

@Vaibhav它只是忽略所有額外的屬性:) –

2

的解決方案,結合new代替override斷裂多態性。最近我遇到了同樣的問題,並按照以下方式實施。我的解決方案具有以下優點:

  • virtualoverride停留在原地;
  • 名稱BaseClass未在鑄型直接使用,因此,如果我在BaseClassDerivedClass之間的層次結構,這也實現了DoSomething()引入一箇中間MiddleClass;那麼MiddleClass的實現將不會被跳過。

這是實現:

public class BaseClass 
{ 
    public virtual void DoSomething() 
    { 
     Trace.Write("base class"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public override void DoSomething() 
    { 
     Trace.Write("derived class"); 
    } 

    public void BaseDoSomething() 
    { 
     base.DoSomething(); 
    } 
} 

用法是:

DerivedClass dc = new DerivedClass(); 

    dc.DoSomething(); 

    dc.BaseDoSomething();