程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> CLR筆記:14.接口

CLR筆記:14.接口

編輯:關於.NET

CLR以及所有托管語言都不支持多繼承,通過接口模擬實現

14.1 類和接口的實現

接口定義:為一組方法簽名指定一個名稱的方式。

類實現接口,就一定要提供接口所有方法的實現。

即使抽象類,也要全部實現,但是,它可以把接口方法聲明為abstract的,從而把這個接口方法留給 派生類去實現,如下:

    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   定義接口

接口中可以有方法/事件/屬性,因為後者本質上也是 方法

接口中不可以有靜態成員(包括常量/枚舉)

接口之間可以"繼承",可以認為是包含另一種接口的約定,並不是真正意義的繼承

接口下所有成員,默認為public,不用聲明

14.3 實現接口

實現的接口方法,一定要標記為public,此時在IL中為virtual和sealed,即不允許子類重寫該方法( 這時new也不管用了)。

要顯示將調用的接口方法標記為virtual,則可以在子類中重寫該方法

//如果顯示標記為sealed,那麼就更不可以重寫了

14.4 調用接口方法

在運行時,可以將一個變量從一種接口類型轉型為另一種接口類型,只要該對象的類型實現了這兩種 接口,如下:

            //String實現了Icloneable, IEnumerable

            String s = "Jax";

            ICloneable cloneable = s;

            IEnumerable enumable = (IEnumerable)cloneable;

注:cloneable只可使用ICloneable的接口方法,不可以使用String的方法;enumable變量雖由 ICloneable轉型而來,但也不能使用ICloneable接口方法。

值類型也可以實現接口,但是在轉成接口類型前要先裝箱——接口變量必須是指向堆上的一個對象的 引用。

//Int32實現了IFormattable接口
Int32 i = 0;
 //i在轉成接口類型前要先裝箱
IFormattable formattable = (IFormattable)i;

14.5    接口方法的隱式/顯示實現

接口方法一般都是隱式實現的,可訪問性一定要聲明為public。

EIMI:顯示接口方法實現,用定義方法的那個接口的名稱來作為方法名稱的前綴。

不屬於類型對象的一部分,只是將一個接口連接到類型上,同時避免了暴露行為和方法

不能指定可訪問性public/private——在IL中標記為為private,只有通過接口變量才能訪問該方法, 以防止類型對象直接訪問。

不能標記為virtual,不能被重寫。

    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個好處

1.編譯時的類型安全性

            Int32 x = 1;

            String s = "1";


            IComparable c = x;

            c.CompareTo(x);

            c.CompareTo(s);             //運行期錯誤,因為Object是不

安全類型


            IComparable<Int32> cc = x;  //強類型,所以直接受整型x,不接受

字符串s,否則編譯期報錯

2.操作值類型時減少裝箱

上個例子將x傳到Compare方法要裝箱,使用泛型不用裝箱,按值傳遞。

非泛型現在仍存在於FCL,是為了向後兼容。

3.同一個類可以實現同一個泛型接口若干次,只要使用不同類型參數

     public sealed class Number : IComparable<Int32>, 

IComparable<String>

    {

        public int CompareTo(int other) { }


        public int CompareTo(string other) { }

    }

可以把IComparable<Int32>和IComparable<String>看作兩個不同的接口,就好理解了。

14.7 泛型接口的參數約束

2個好處:

1.可以將類型參數約束為多個接口,從而使傳入的參數類型必須實現所有接口約束

2.減少裝箱

參數約束,會生成特定的IL語言,使得直接在值類型上調用接口方法,而不用裝箱。

14.9    用EIMI改進編譯時類型安全

使用EIMI技術,處理非泛型接口,保證類型安全

    struct SomeValueType : IComparable

    {

        private Int32 m_x;
        public SomeValueType(Int32 x)

        {

            m_x = x;

        }
        //這是一個類型安全的方法

        public Int32 CompareTo(SomeValueType other)

        {

            return m_x - other.m_x;

        }
        //這是一個類型不安全的方法,但是一定要有,才能保證編譯通過,因為參數不同,可

以認為是重載,而且這個方法才是接口方法的實現

        Int32 IComparable.CompareTo(Object other)

        {

            return CompareTo((SomeValueType)other);

        }

    }

調用的時候要注意:

            SomeValueType v = new SomeValueType();

            Object o = new Object();


            Int32 n = v.CompareTo(v);   //類對象v的Comapre方法,保證類型安全


            IComparable c = v;

            n = c.CompareTo(v);

            n = c.CompareTo(o);         //接口對象c的Comapre方法,不能保

證類型安全,所以不要使用接口對象

14.10 EIMI的缺點

3個缺點:

1.沒有說明具體如何實現一個EIMI方法

2.值類型實例在轉換為接口類型時,會被裝箱

3.EIMI方法不能被派生類型繼承

14.11 接口與類繼承

類繼承: 表示 IS-A。易於使用,不必提供所有實現;可以override和new重寫;易於在基類中添加成 員,而不需改動子類

接口: 表示 CAN-DO。以上類繼承的優點一概沒有。

值類型繼承自System.ValueType,只能使用接口

FCL的集合基於接口,因為各種集合間極少共享的代碼。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved