zoukankan      html  css  js  c++  java
  • CLR笔记:14.接口

    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的集合基于接口,因为各种集合间极少共享的代码。


  • 相关阅读:
    HIVE 技巧积累之合并重叠日期
    记一次hive版本升级
    【转】elasticsearch中字段类型默认显示{ "foo": { "type": "text", "fields": { "keyword": {"type": "keyword", "ignore_above": 256} }
    【转】深入理解Linux修改hostname
    VMware中 CentOS7挂载windows共享文件夹
    Apache版hadoop编译
    No route info of this topic
    java遍历文件夹及所有子文件
    关闭spring整合kafka时,消费者一直打印kafka日志
    (转)详解shell中>/dev/null 2>&1到底是什么
  • 原文地址:https://www.cnblogs.com/Jax/p/906855.html
Copyright © 2011-2022 走看看