2009-01-13 47 views
2

類外側的底部方法我有兩個類:強制調用從派生

public class MyBase 
{ 
    public virtual void DoMe() 
    { 

    } 
} 

public class MyDerived:MyBase 
{ 
    public override void DoMe() 
    { 
     throw new NotImplementedException(); 
    } 
} 

和我有下面的代碼實例MyDerived:

 MyDerived myDerived=new MyDerived(); 

的事情是如何調用的圓頂基類?如果我使用myDerived.DoMe(),則派生的方法將被調用,從而導致異常。我試圖將myDerived轉換爲MyBase,但它仍然是被調用的方法的派生版本。

編輯:正如在下面的評論中提到的,我無法更改eitehr MyDerived或MyBase,因爲它們不是我的代碼。

+0

這是封裝和信息隱藏,我不認爲有一個真正的答案,它的徹底的黑客。不知道有關反射雖然... – 2009-05-14 05:03:41

回答

0
public class MyDerived:MyBase{  
    public override void DoMe()  
    {   
     base.DoMe(); 
    } 
} 

編輯:

不通過子類方法去您不能訪問從「外部」的基類方法。你唯一的選擇是直接實例化你的基類,並調用它的方法。

MyBase mb = new MyBase(); 
mb.DoMe(); 
+0

我可以訪問派生類中的基類方法,但我想從外部訪問。 – Graviton 2009-01-13 04:16:13

+0

在這種情況下,您的設計出現問題。 – JasonTrue 2009-01-13 05:48:59

0

爲了從外部調用類MyBase.DoMe(),您將需要或者MyBase的實例或派生實例不會覆蓋圓頂()。聲明爲虛擬的方法將在對象的實際運行時類型上調用,而不是對象的類型,這就是爲什麼轉換爲MyBase不會更改調用哪種方法的原因。但是如果該方法沒有在MyBase中聲明爲虛擬的,MyDerived仍然實現了DoMe(),它將「隱藏」MyBase的實現。因此,如果引用是MyDerived,它會調用MyDerived.DoMe(),但在這種情況下,投射到MyBase myBase =(MyBase)myDerived,然後調用myBase.DoMe()將調用MyBase.DoMe()。

2

您無法調用基類版本。

如果該方法在派生類上不起作用,那麼當調用派生類的實例時,該方法的基本版本將不起作用。這只是要求麻煩。課堂並不是以這種方式工作的,你想要做的事情可能會導致課堂的其他部分表現出不可預測的行爲。

爲什麼當對象完全告訴你它不起作用時,你需要在對象上調用這個方法?

在我看來,這些類有一些設計缺陷,如果您不允許更改類,也許您可​​以改爲更好設計的庫。

0

派生類不需要提供方法的實現。刪除它,基類中的實現將被默認調用。

如果與您的示例不同,基類中的方法是抽象的,並且您必須提供實現,但它對於派生類提供的實現沒有意義,那麼類的設計可能有問題。

0

由於您的限制,存在另一種可能性:

下載.Net Reflector。反編譯現有代碼,然後進行任何需要支持您的情況的更改。

當然,在繼續之前檢查一下它的合法性。

2

有一種解決方案,但它很醜陋:使用反射來獲取基類方法,然後發出調用它所需的IL。查看this blog post,它說明了如何做到這一點。我已經成功地使用這種方法來調用基類的一個方法的實現,當我擁有的是一個派生類的參考覆蓋該方法。

0

這個問題是這麼老了,但我沒有看到下面的選項:

可以使用new關鍵字來指定重疊的方法。然後,您只需投射到您希望打電話的方法。

public class MyBase 
    { 
     public virtual void DoMe() 
     { 

     } 
    } 

    public class MyDerived:MyBase 
    { 
//note the use of 'new' and not 'override' 
     public new void DoMe() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

實施

var myDerived = new MyDerived(); 
var derivedDoMe = myDerived.DoMe(); 
var baseDoMe = ((MyBase)myDerived).DoMe();