區分介面實現與虛函數重載

來源:互聯網
上載者:User

 眾所周知,在一個類中對介面所定義方法的實現,預設是不會加上“virtual”關鍵字的。

一般的形式如下。

    interface IMsg

    {
        void Message();
    }

    public class MyClass:IMsg
    {
        #region IMsg Members
        public void Message()
        {
            // TODO: Add MyClass.Message implementation
            Debug.WriteLine( "MyClass" );
        }
        #endregion
    }

因此,那麼如果一個類型繼承了實現介面的類型,預設的情況下是無法重載介面所定義的方法。不過在子類中雖說可以用“new”關鍵字覆蓋父類的方法,但是這並不能代替介面所定義的方法,例如:

    public class MyDerivedClass:MyClass
    {
        public new void Message()
        {
            Debug.WriteLine( "MyDerivedClass" );
        }
    }

    //Only for test
    MyDerivedClass d = new MyDerivedClass();
    d.Message();// Prints “MyDerivedClass”
    IMsg m = d as IMsg;
    m.Message();// Prints “MyClass”

很明顯,這樣的寫法並不能達到我們真正想要的目的。那麼如何在多層繼承中,能使介面實現局部化,簡單說,就是在不同的類型中有不同的實現方法。一般來說,需要在原有的基礎上進行轉化,通常有四種解決方案。

第一種方法,在子類中增加介面標識,這樣就可以名正言順實現介面定義的方法。例如如上的改寫。

public class MyDerivedClass:MyClass, IMsg
{
        public new void Message()
        {
            Debug.WriteLine( "MyDerivedClass" );
        }
    }

那麼如上改寫,對於前一部分測試代碼來說,運行正確;但是這樣的實現會存在潛在的Bug,例如:

    //Only for test

    MyDerivedClass d = new MyDerivedClass();

    d.Message();//Print "MyDerivedClass"

    IMsg m = d as IMsg;

    m.Message();//Print "MyDerivedClass"

    MyClass b = d;

    b.Message();//Print "MyClass"

也就是說,這樣方法可以解決介面在多層繼承中的問題,但是處理得不完美。相對於這種方法,另外三種方法要好很多,但是這三種方法都牽扯到虛函數。

首先介紹的,也是最簡單的,就是在實現的時候,給介面定義的函數增加“virtual”標識。例如:

    public class MyClass:IMsg

    {

        #region IMsg Members

        public virtual void Message()

        {

            // TODO: Add MyClass.Message implementation

            Debug.WriteLine( "MyClass" );

        }

        #endregion

    }

    public class MyDerivedClass:MyClass

    {

        public override void Message()

        {

            Debug.WriteLine( "MyDerivedClass" );

        }

    }

不過,我覺得這個方法有些投機,或者從某種意義上說,已經變更了介面定義。

那麼接下來介紹的,就是用抽象類別進行重新封裝。例如:

    public abstract class MyClass:IMsg

    {

        #region IMsg Members

        public abstract void Message();

        #endregion

    }

這種方法相對前面的一種方法來說,是比較正規的,但是給人一種多此一舉的感覺,除非為了後期能提供IMsg介面轉換,否則直接用如下的方式會更好。

    public abstract class MyClass

    {

        public abstract void Message();

    }

最後一種實現,也是我比較喜歡的一種,類似於以前文章中提到的IDisposable實現方法,那麼對於這個例子,可以如下改寫。

    public class MyClass:IMsg

    {

        #region IMsg Members

        public void Message()

        {

            // TODO: Add MyClass.Message implementation

            ShowMessage();

        }

        #endregion

        protected virtual void ShowMessage()
        {
            Debug.WriteLine( "MyClass" );
        }
    }

    public class MyDerivedClass:MyClass

    {
        protected override void ShowMessage()

        {
             Debug.WriteLine( "MyDerivedClass" );
        }

    }

這樣的改寫,既保留介面的完整性,同時代碼比較直觀,介面實現是介面實現,虛函數重載是虛函數重載,兩者是分離的。不過相對於前兩個虛函數實現方法,這一個方法需要編寫的代碼要相對多一些,效率略低(因為調用介面方法需要調用兩個函數)。

介面只是聲明方法和屬性,方法的一些標識並沒有特殊限制,因此在實現的時候可以增加一些標識,除了“virtual”外,還有“abstract”和“sealed”。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.