類和接口的實(shí)現(xiàn)
接口定義:為一組方法簽名指定一個(gè)名稱的方式。
類實(shí)現(xiàn)接口,就一定要提供接口所有方法的實(shí)現(xiàn)。
即使抽象類,也要全部實(shí)現(xiàn),但是,它可以把接口方法聲明為abstract的,從而把這個(gè)接口方法留給派生類去實(shí)現(xiàn),如下:
    public interface ITest 
    {
        void Test();
    }
    public abstract class AbstractClass : ITest
    {
        public abstract void Test();
    }
    public class ConcreateClass : AbstractClass
    {
        public override void Test()
        {
            //Coding implementation;
        }
    }
14.2 定義接口
接口中可以有方法/事件/屬性,因?yàn)楹笳弑举|(zhì)上也是 方法
接口中不可以有靜態(tài)成員(包括常量/枚舉)
接口之間可以"繼承",可以認(rèn)為是包含另一種接口的約定,并不是真正意義的繼承
接口下所有成員,默認(rèn)為public,不用聲明
14.3 實(shí)現(xiàn)接口
實(shí)現(xiàn)的接口方法,一定要標(biāo)記為public,此時(shí)在IL中為virtual和sealed,即不允許子類重寫(xiě)該方法(這時(shí)new也不管用了)。
要顯示將調(diào)用的接口方法標(biāo)記為virtual,則可以在子類中重寫(xiě)該方法
//如果顯示標(biāo)記為sealed,那么就更不可以重寫(xiě)了
14.4 調(diào)用接口方法
在運(yùn)行時(shí),可以將一個(gè)變量從一種接口類型轉(zhuǎn)型為另一種接口類型,只要該對(duì)象的類型實(shí)現(xiàn)了這兩種接口,如下:
            //String實(shí)現(xiàn)了Icloneable, IEnumerable
            String s = "Jax";
            ICloneable cloneable = s;
            IEnumerable enumable = (IEnumerable)cloneable;
注:cloneable只可使用ICloneable的接口方法,不可以使用String的方法;enumable變量雖由ICloneable轉(zhuǎn)型而來(lái),但也不能使用ICloneable接口方法。
值類型也可以實(shí)現(xiàn)接口,但是在轉(zhuǎn)成接口類型前要先裝箱——接口變量必須是指向堆上的一個(gè)對(duì)象的引用。
            //Int32實(shí)現(xiàn)了IFormattable接口
            Int32 i = 0;
            //i在轉(zhuǎn)成接口類型前要先裝箱
            IFormattable formattable = (IFormattable)i;
14.5 接口方法的隱式/顯示實(shí)現(xiàn)
接口方法一般都是隱式實(shí)現(xiàn)的,可訪問(wèn)性一定要聲明為public。
EIMI:顯示接口方法實(shí)現(xiàn),用定義方法的那個(gè)接口的名稱來(lái)作為方法名稱的前綴。
不屬于類型對(duì)象的一部分,只是將一個(gè)接口連接到類型上,同時(shí)避免了暴露行為和方法
不能指定可訪問(wèn)性public/PRivate——在IL中標(biāo)記為為private,只有通過(guò)接口變量才能訪問(wèn)該方法,以防止類型對(duì)象直接訪問(wèn)。
不能標(biāo)記為virtual,不能被重寫(xiě)。
    public interface ITest 
    {
        void Test();
    }
    public class TestClass : ITest
    {
        public void Test()
        {
            Console.WriteLine("1");
        }
        void ITest.Test() 
        {
            Console.WriteLine("2");        
        }
    }            TestClass t = new TestClass();
            t.Test();                       //輸出1
            ITest it = (ITest)t;
            it.Test();                      //輸出2
14.6 泛型接口
3個(gè)好處
1.編譯時(shí)的類型安全性
            Int32 x = 1;
            String s = "1";
            IComparable c = x;
            c.CompareTo(x);
            c.CompareTo(s);             //運(yùn)行期錯(cuò)誤,因?yàn)镺bject是不安全類型
            IComparable<Int32> cc = x;  //強(qiáng)類型,所以直接受整型x,不接受字符串s,否則編譯期報(bào)錯(cuò)    
2.操作值類型時(shí)減少裝箱
上個(gè)例子將x傳到Compare方法要裝箱,使用泛型不用裝箱,按值傳遞。
非泛型現(xiàn)在仍存在于FCL,是為了向后兼容。
3.同一個(gè)類可以實(shí)現(xiàn)同一個(gè)泛型接口若干次,只要使用不同類型參數(shù)
     public sealed class Number : IComparable<Int32>, IComparable<String>
    {
        public int CompareTo(int other) { }
        public int CompareTo(string other) { }
    }
可以把IComparable<Int32>和IComparable<String>看作兩個(gè)不同的接口,就好理解了。
14.7 泛型接口的參數(shù)約束
2個(gè)好處:
1.可以將類型參數(shù)約束為多個(gè)接口,從而使傳入的參數(shù)類型必須實(shí)現(xiàn)所有接口約束
2.減少裝箱
參數(shù)約束,會(huì)生成特定的IL語(yǔ)言,使得直接在值類型上調(diào)用接口方法,而不用裝箱。
14.9 用EIMI改進(jìn)編譯時(shí)類型安全
使用EIMI技術(shù),處理非泛型接口,保證類型安全
    struct SomeValueType : IComparable
    {
        private Int32 m_x;
        public SomeValueType(Int32 x)
        {
            m_x = x;
        }
        //這是一個(gè)類型安全的方法
        public Int32 CompareTo(SomeValueType other)
        {
            return m_x - other.m_x;
        }
        //這是一個(gè)類型不安全的方法,但是一定要有,才能保證編譯通過(guò),因?yàn)閰?shù)不同,可以認(rèn)為是重載,而且這個(gè)方法才是接口方法的實(shí)現(xiàn)
        Int32 IComparable.CompareTo(Object other)
        {
            return CompareTo((SomeValueType)other);
        }
    }
調(diào)用的時(shí)候要注意:
            SomeValueType v = new SomeValueType();
            Object o = new Object();
            Int32 n = v.CompareTo(v);   //類對(duì)象v的Comapre方法,保證類型安全
            IComparable c = v;
            n = c.CompareTo(v);
            n = c.CompareTo(o);         //接口對(duì)象c的Comapre方法,不能保證類型安全,所以不要使用接口對(duì)象
14.10 EIMI的缺點(diǎn)
3個(gè)缺點(diǎn):
1.沒(méi)有說(shuō)明具體如何實(shí)現(xiàn)一個(gè)EIMI方法
2.值類型實(shí)例在轉(zhuǎn)換為接口類型時(shí),會(huì)被裝箱
3.EIMI方法不能被派生類型繼承
14.11 接口與類繼承
類繼承: 表示 IS-A。易于使用,不必提供所有實(shí)現(xiàn);可以override和new重寫(xiě);易于在基類中添加成員,而不需改動(dòng)子類
接口: 表示 CAN-DO。以上類繼承的優(yōu)點(diǎn)一概沒(méi)有。
值類型繼承自System.ValueType,只能使用接口
FCL的集合基于接口,因?yàn)楦鞣N集合間極少共享的代碼。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注