• CLR via C#学习笔记-第十三章-定义接口、继承接口


    13.1 类和接口继承

    接口是为了实现多继承

    所有的类都继承了System.Object,及其四个公共实例方法:ToString、Equals、GetHashCode、GetType。

    CLR允许定义接口,它实际只是对一组方法签名进行了统一命名。这些方法不提供任何实现。

    类通过指定接口名称来继承接口,而且必须显式实现接口方法,否则CLR认为此类型定义无效。

    实现接口方法的过程比较繁琐,所以说接口继承是实现多继承的一种缩水版机制。

    编译器和CLR允许一个类继承多个接口,继承的所有接口都必须实现。

    接口继承特点

    类继承的一个重要特点是,凡是能使用基类型实例的地方,都能使用派生类型的实例。

    类似的,凡是能够使用具名接口类型的实例的地方,都能使用实现了接口的一个类型的实例。

    13.2 定义接口

    接口还能定义事件、无参属性和有参属性。

    所有这些东西的本质上都是方法,他们只是语法上的简化。

    不过接口不能定义任何构造器方法,也不能定义任何实例字段。

    接口不能定义静态成员

    CLR允许接口定义静态方法、字段、常量和构造器,但符合CLS标准的接口决不允许,C#禁止接口定义任何一种静态成员。

    接口定义就是类型定义

    在CLR看来,接口定义就是类型定义。

    也就是说CLR会为接口类型对象定义内部数据结构,同时可通过反射机制来查询接口类型的功能。

    和类型一样,接口可在文件范围中定义,也可嵌套在另一个类型中。定义接口类型时可指定你希望的任何可见性、可访问性。

    接口继承不是严格的继承

    接口定义可以从另一个或多个接口继承。但它不是严格的继承。

    接口继承的工作方式并不完全和类继承一样。

    作者倾向于将接口结成看成是将其他接口的协定contract包括到2新接口中。

    例如ICollection<T>接口定义包含了IEnumerable<T>和IEnumerable两个接口的协定,有下面两层含义:

    1.继承ICollection<T>接口的任何类必须实现ICollection<T>、IEnumerable<T>和IEnumerable三个接口所定义的方法。

    2.任何代码在引用实现ICollection<T>接口的对象时,该类型还实现了IEnumerable<T>和IEnumerable接口。

    13.3 继承接口

    显式为实现接口的方法标记virtual和隐式的区别

    编译器要求将实现接口的方法标记为public。

    CLR要求将接口方法标记为virtual,编译器会将他们标记为virtual和sealed。这会阻止派生类重写接口方法。

    将方法显式标记为virtual,编译器就会将该方法标记为virtual并保持它的非密封状态,使派生类能重写它。

    派生类重写基类实现的接口方法

    派生类不能重写sealed的接口方法,但派生类可重新继承同一个接口,并为接口方法提供自己的实现。

    下例对此进行了演示:

    //派生自Object,他实现了IDisposable
    internal class Base:IDisposable{
        public void Dispose(){
            Console.WriteLine("Base's Dispose");
        }
    }
    //重新实现了IDisposable
    internal class Derived:Base,IDisposable{
        new public void Dispose(){
            Console.WriteLine("Base's Dispose");
        }
    }

    在Main函数中进行调用:

    /*****************第一个例子****************/
    Base b=new Base();
    //用b的类型调用Dispose,显示"Base's Dispose"
    b.Dispose();
    //用b的对象的类型调用Dispose,显示"Base's Dispose"
    ((IDisposable)b).Dispose();
    
    /*****************第二个例子****************/
    Derived d=new Derived();
    //用d的类型调用Dispose,显示"Derived's Dispose"
    d.Dispose();
    //用d的对象的类型调用Dispose,显示"Derived's Dispose"
    ((IDisposable)d).Dispose();
    
    /*****************第三个例子****************/
    b=new Derived();
    //用b的类型调用Dispose,显示"Base's Dispose"
    b.Dispose();
    //用b的对象的类型调用Dispose,显示"Derived's Dispose"
    ((IDisposable)b).Dispose();
  • 相关阅读:
    JAVA_基础集合List接口与Set接口(二)
    JAVA_基础集合Collection接口与Iterator迭代器(一)
    JAVA_基础注解的概念
    JAVA_基础多线程的生命周期、线程安全、线程锁、线程通信与创建线程(二)
    JAVA_基础多线程(一)
    JAVA_基础异常概述与异常体系的结构
    JAVA_基础内部类
    JAVA_基础面向对象:接口
    Golang 学习资源
    go语言-异常处理机制-panic和recover的使用和原理
  • 原文地址:https://www.cnblogs.com/errornull/p/9905469.html
Copyright © 2020-2023  润新知