2012-03-09 93 views
4

首先看一下這個代碼:接口繼承一致性

class Program 
{ 
    static void Main(string[] args) 
    { 
    var x =(Base) new Derived(); 
    ((IMethod)x).DoWork(); 

    Console.ReadKey(); 
    } 
} 

interface IMethod 
{ 
    void DoWork(); 
} 

abstract class Base : IMethod 
{ 
    void IMethod.DoWork() 
    { 
    Console.WriteLine("Base.DoWork"); 
    } 
} 

class Derived : Base, IMethod 
{ 
    public void DoWork() 
    { 
    //here I where I want to call base.DoWork(); 
    Console.WriteLine("Derived.DoWork"); 
    } 
} 

輸出:

Derived.DoWork 

期望:

Base.DoWork 
Derived.DoWork 

我處理暴露,當一個接口的API在遊行的某些部分將會調用DoWork方法。

現在在上面的例子中,類Base是API的一部分,它在內部(在API中)已經明確地實現了該接口並在DoWork方法中執行了一些重要的執行。

我需要重寫我的派生類中的IMethod的實現,所以在需要時我會得到通知,問題是我無法「覆蓋」該方法並調用基方法,也無法投射基到IMethod

任何解決方案?

注意:反射不起作用,因爲它是一個Silverlight項目,禁止私人方法調用。

+0

爲什麼要混合使用兩種風格的界面實現? – dkackman 2012-03-09 01:36:29

+2

你的基類顯然不是用這種繼承來設計的;通常基類將提供一個受保護的虛擬方法,如果他們希望允許覆蓋該行爲,則實現顯式實現的邏輯。鑑於此,即使您可以找到方法來「強制」這種覆蓋行爲也是有風險的,因爲您是以原始開發人員沒有設計的方式從類中有效地派生出來的。這就是說,這仍然是一個有趣的問題。 – 2012-03-09 01:38:35

+0

@DanBryant,讓我們把設計放在一邊(除此之外別無選擇),但不要忘記我需要像基類一樣實現接口,並且必須調用這兩種方法。看到我更新的答案。 – Shimmy 2012-03-09 03:22:32

回答

1

我發現DanBryant's comment是答案,雖然他提到有點冒險,因爲我們不能保證實施者會調用基本方法,但是是一個體面的方法壽。

我做了一個受保護的虛擬方法,從私有接口實現者調用,然後,在派生類中,而不是擔心接口,我只關心覆蓋基類並從中調用基類實現,完美的作品,例如:

abstract class Base : IMethod 
{ 
    void IMethod.DoWork() 
    { 
    DoWork(); 
    } 

    protected virtual void DoWork() 
    { 
    Console.WriteLine("Base.DoWork"); 
    } 
} 

class Derived : Base 
{ 
    protected override void DoWork() 
    { 
    base.DoWork(); 
    //here I where I want to call base.DoWork(); 
    Console.WriteLine("Derived.DoWork"); 
    } 
} 
1

你是否在尋找:

public class Derived : Base 
{ 
    public override void DoWork() 
    { 
     base.DoWork(); 
    } 
} 
+3

那不行; 'Base'實際上並沒有一個名爲'DoWork()'的方法。 – dlev 2012-03-09 01:20:20

+0

啊,你說得對。我沒有注意到它使用了接口實現。 @Shimmy是否可以將方法的定義更改爲_不明確實現接口(例如'public virtual void DoWork()')? – pickypg 2012-03-09 01:43:00

3

你能剛組成的類,而不是使用繼承?然後,您可以實現DoWork(),但不管您是否喜歡,並仍然在Base對象上調用DoWork()。由於Base是抽象的,因此您需要派生一個虛擬類型以使所有內容都可以正常工作。

class Derived : IMethod 
{ 
    private class SneakyBase : Base 
    { 
     // abstract implementations here 
    } 

    private IMethod baseObject = new SneakyBase(); 

    void DoWork() 
    { 
     baseObject.DoWork(); 

     // Custom DoWork code here 
    } 
} 

這顯然是一個有點疼痛做的事情這樣的,但是API設計者提供了顯式接口實現做出一個奇怪的選擇,而你現在爲它付出。

+0

Nah。基類是抽象的!此外,在我的情況下,我不得不重寫它。 – Shimmy 2012-03-09 01:32:22

+0

@Shimmy看到編輯。偷偷摸摸! – dlev 2012-03-09 01:34:01