一、接口

在日常生活中,手机、笔记本电脑、平板电脑等电子产品提供了不同类型的接口用于充电或者连接不同的设备。

不同类型接口的标准不一样,例如电压、尺寸等。

在C#语言中,接口也会定义一种标准,如果需要使用接口,必须满足接口中所定义的内容。

在C#语言中,类之间的继承关系仅支持单重继承,而接口是为了实现多重继承关系设计的。

一个类能同时实现多个接口,还能在实现接口的同时再继承其他类,并且接口之间也可以继承。

(总之,就是像类一样。)

(如果换个思路的话,这其实就是一种用关键字interface替换关键字class来定义的类,然后一样的继承重写和调用。)

(不禁让人怀疑,这是为了对class类进行完善,但又没办法在原有的基础上修改,所以才进行的重新定义和编写。也就由于class关键字被占用,所以就用了关键字interface。【自己的胡乱揣测,还是以事实为依据,这里不要过于相信。】)

二、interface:定义接口

表达形式:

interface  接口名称
        {
            接口成员;
        }

例:

interface IA{  int Id { get; set; }  void Total();}

其中:

在定义接口名称时,为了跟class类进行区分,会在接口的命名中的头部,追加一个大写的“i”。

接口成员虽然与类相似,但还要注意以下区别。

  • ‍接口中的成员不允许使用 public、private、protected、internal 访问修饰符。

  • 接口中的成员不允许使用 static、virtual、abstract、sealed 修饰符。

  • 在接口中不能定义字段。

  • 在接口中定义的方法不能包含方法体。

也就是变量不能赋值,方法为抽象类。

一个类能同时实现多个接口,还能在实现接口的同时再继承其他类,并且接口之间也可以继承。
    无论是表示类之间的继承还是类实现接口、接口之间的继承,都使用“:”来表示。

1.例

创建一个接口计算学生成绩的接口 ICompute,并在接口中分别定义计算总成绩、平均成绩的方法。
        根据题目要求,在该接口中定义学生的学号、姓名的属性,并定义计算成绩的总分和 平均分的方法。

interface ICompute{    int Id { get; set; }    string Name { get; set; }    void Total();    void Avg();}

分析:

用interface关键字定义接口,并且接口的名称首字母是大写的“i”。

然后里面的字段和方法,都没有明确赋值。

字段采用的是get和set的访问器。

方法是抽象方法,不过并没有进行关键字的声明,因为不需要。

由于接口中的方法并没有具体的内容,直接调用接口中的方法没有任何意义。

在 C# 语言中规定不能直接创建接口的实例,只能通过类实现接口中的方法。

三、实现接口的两种方式:显示实现和隐式实现接口

接口的实现实际上和类之间的继承是一样的,也是重写了接口中的方法,让其有了具体的实现内容。
    但需要注意的是,在类中实现一个接口时必须将接口中的所有成员都实现,否则该类必须声明为抽象类,并将接口中未实现的成员以抽象方式实现。

实现接口的具体语法形式如下

class  类名 : 接口名
        {
            //类中的成员以及实现接口中的成员
        }

例:

interface IA{  int Id { get; set; }  void Total();}class B : IA{  public int Id { get; set; }  public void Total(){    Console.WriteLine("aaa");  }}

这是直接使用。

注意的是,在继承接口时,必须把所以成员实现。

追加public关键字,否则也会出错。

例:

以抽象方式实现接口中的成员是指将接口中未实现的成员定义为抽象成员,示例代码如下。

interface ITest{    string name { get; set}    void Print();}abstract class Test : ITest{    public abstract string name { get; set; }    public abstract void Print();}

分析:

这是用抽象类进行了继承。

而抽象类需要用关键字abstract进行定义,同时也跟接口一样,方法内部不能有方法体。

上述中,将接口中未实现的属性和方法分别定义为抽象属性和抽象方法,来实现将类定义为抽象类。

这是一种特殊的实现方式,在实际应用中通常是将接口中的所有成员全部实现。

在实现接口的成员时有两种方式,一种是隐式实现接口成员,一种是显式实现接口成员。

在实际应用中隐式实现接口的方式比较常用,由于在接口中定义的成员默认是 public 类型的,隐式实现接口成员是将接口的所有成员以 public 访问修饰符修饰。

显式实现接口是指在实现接口时所实现的成员名称前含有接口名称作为前缀。

需要注意的是使用显式实现接口的成员不能再使用修饰符修饰,即 public、abstract、virtual、 override 等。

1.例

通过实例来演示在编程中隐式实现接口与显式实现接口有什么区别。

根据题目要求,首先使用隐式方式来实现接口 ICompute 的成员,以计算机专业的学生类 (ComputerMajor) 实现 ICompute 接口,为其添加英语 (English)、编程 (Programming)、数据库 (Database) 学科成绩属性。

隐式的实现,代码如下。

class ComputerMajor : ICompute{    public int Id { get; set; }     //隐式的实现接口中的属性    public string Name { get; set; }    //隐式实现接口中的属性    public double English { get; set; }    public double Programming { get; set; }    public double Database { get; set; }    public void Avg()       //隐式实现接口中的方法    {        double avg = (English + Programming + Database) / 3;        Console.WriteLine("平均分:" + avg);    }    public void Total()    {        double sum = English + Programming + Database;        Console.WriteLine("总分为:" + sum);    }}

分析:

这是类继承接口的代码。

可以看到,都追加了public修饰符,并且在方法中都追加了方法体。

关于字段,由于使用的是set和get访问器,因而也算拥有了默认值。

由于在接口中定义的成员默认是 public 类型的,隐式实现接口成员是将接口的所有成员以 public 访问修饰符修饰。

在 Main 方法中调用该实现类的成员,代码如下。

class Program{    static void Main(string[] args)    {        ComputerMajor computerMajor = new ComputerMajor();        computerMajor.Id = 1;        computerMajor.Name = "李明";        computerMajor.English = 80;        computerMajor.Programming = 90;        computerMajor.Database = 85;        Console.WriteLine("学号:" + computerMajor.Id);        Console.WriteLine("姓名:" + computerMajor.Name);        Console.WriteLine("成绩信息如下:");        computerMajor.Total();        computerMajor.Avg();    }}

分析:

在Main()方法中进行声明创建。

然后利用set访问器的特性进行赋值,以及方法的调用。

(基本上还是这些,就是多了些不同的规则。)

2.例

使用显式方式来实现接口成员的代码如下。

class ComputerMajor : ICompute{    public double English { get; set; }    public double Programming { get; set; }    public double Database { get; set; }    int ICompute.Id { get; set; }           //显示实现接口中的属性    string ICompute.Name { get; set; }      //显示实现接口中的属性    void ICompute.Total()                   //显示实现接口中的方法    {        double sum = English + Programming + Database;        Console.WriteLine("总分数:" + sum);    }    void ICompute.Avg()    {        double avg = (English + Programming + Database) / 3;        Console.WriteLine("平均分为:" + avg);    }}

分析:

3~5行,依旧是隐式方式。

而显示的方式,就好像使用了static静态声明了一样,直接用接口名称进行调用改写。

并且还需要注意的是使用显式实现接口的成员不能再使用修饰符修饰,即 public、abstract、virtual、 override 等。

在Main方法中调用实现类中的成员,代码如下

class Program{    static void Main(string[] args)    {        ComputerMajor computerMajor = new ComputerMajor();                ICompute compute = computerMajor;       //创建接口的实例        compute.Id = 1;        compute.Name = "李明";                computerMajor.English = 80;        computerMajor.Programming = 90;        computerMajor.Database = 85;        Console.WriteLine("学号:" + compute.Id);        Console.WriteLine("姓名:" + compute.Name);        Console.WriteLine("成绩信息如下:");                compute.Total();        compute.Avg();    }}

分析:

不仅创建了类的实例,还创建了接口的实例。

采用隐式方式的部分,用类的实例赋值调用。

而显示方式的部分,居然用接口的实例进行赋值调用。

在调用显式方式实现接口的成员时,必须使用接口的实例来调用,而不能使用实现类的实例来调用。

与类之间的继承类似,实现类的实例也可以隐式转换为其所实现接口的接口类型。

接口与抽象类的区别入下表所示。

接口 抽象类
在接口中仅能定义成员,但不能有具体的实现。 抽象类除了抽象成员以外,其他成员允许有具体的实现。
在接口中不能声明字段,并且不能声明任何私有成员,成员不能包含任何修饰符。 在抽象类中能声明任意成员,并能使用任何修饰符来修饰。
接口能使用类或者结构体来继承。 抽象类仅能使用类继承。
在使用类来实现接口时,必须隐式或显式地实现接口中的所有成员,否则需要将实现类定义为抽象类,并将接口中未实现的成员以抽象的方式实现。 在使用类来继承抽象 类时允许实现全部或部分成员,但仅实现其中的部分成员,其实现类必须也定义为抽象类。
一个接口允许继承多个接口。 一个类只能有一个父类。

四、接口中多态的实现

在前面学过多态能使用类之间的继承关系来实现,通过多个类继承同一个接口,并实现接口中的成员也能完成多态的表示。
    使用接口实现多态 需要满足以下两个条件。

  • 定义接口并使用类实现了接口中的成员。

  • 创建接口的实例指向不同的实现类对象。

1.例

假设接口名称为 ITest,分别定义两个实现类来实现接口的成员,示例代码如下。

interface ITest{    void methodA();}class Test1 : ITest{    public void methodA()    {        Console.WriteLine("Test1 类中的 methodA 方法");    }}class Test2 : ITest{    public void methodA()    {        Console.WriteLine("Test2 类中的 methodA 方法");    }}

使用多态的方式调用实现类中的方法,Main 方法中的代码如下。

class Program{    static void Main(string[] args)    {        ITest test1 = new Test1();  //创建接口的实例test1指向实现类Test1的对象        test1.methodA();        ITest test2 = new Test2();  //创建接口的实例test2指向实现类Test2的对象        test2.methodA();    }}

分析:

定义接口,和定义两个拥有继承的类就没什么好说的了。

然后就是这声明调用。

这里用的是接口的名称作为数据类型,也就类似用父类的名称做数据类型。

可以看出,使用不同类实现同一接口的方法输出的内容各不相同,这就是使用接口的方式实现多态的方法。

跟类的多态基本上一样,并且统一数据类型的好处就是上一句说说的。

不同类实现同一接口的方法,统一了数据类型,也就更好的传参。

1.例

创建绘制图形的接口,分别使用两个类来实现接口绘制不同的图形。

根据题目要求,在绘制图形的接口中包括图形面积、坐标、颜色属性,并编写一个方法输出图形的描述,即属性值。

接口定义的代码如下。

interface IShape{    double Area { get; }    double X { get; set; }    double Y { get; set; }    string Color { get; set; }    void Draw();}

分析:

定义了接口IShape。

然后按照题意,往里面放置变量。

最后还编写了一个方法。

(因为是接口,所以不能有方法体和变量值,同时也不能添加修饰符。)

下面分别使用矩形类 (Rectangle) 和圆类 (Circle) 实现该接口,并实现接口中的所有成员,代码如下。

class Rectangle :IShape{    //为矩形的长和宽赋值    public Rectangle(double length,double width)    {        this.Length = length;        this.Width = width;    }    public double Length { get; set; }//定义长方形的长度    public double Width { get; set; }//定义长方形的宽度    public double Area    {        get        {            return Length * Width;//计算长方形面积        }    }    public string Color { get; set; }    public double X { get; set; }    public double Y { get; set; }    public void Draw()    {        Console.WriteLine("绘制图形如下:");        Console.WriteLine("在坐标 {0},{1} 的位置绘制面积为 {2} 颜色为 {3} 的矩形", X, Y, Area, Color);    }}class Circle : IShape{    //为圆的半径赋值    public Circle(double radius)    {        this.Radius = radius;    }    public double Radius { get; set; }    public double Area    {        get        {            return Radius * Radius * 3.14;        }    }    public string Color { get; set; }    public double X { get; set; }    public double Y { get; set; }    public void Draw()    {        Console.WriteLine("绘制图形如下:");        Console.WriteLine("在坐标为 {0},{1} 的位置绘制面积为 {2} 颜色为 {3} 的圆形", X, Y, Area, Color);    }}

分析:

1~26行,为矩形类。

里面定义了矩形类的构造函数,为矩形的长和宽赋值。

又追加了长和宽,变量Length和变量Width。

为Area面积变量添加了返回值,可直接返回长方形的面积。

然后就是将接口里的字段变量和方法,都改成类的实现。

追加public,并为Draw方法添加方法体。也就是图形的描述。

27~50行,为圆类。

同样添加了圆类的构造函数,为圆的半径赋值。

又追加了半径变量Radius。

为Area面积变量添加了返回值,可直接返回圆形的面积。

然后就是将接口里的字段变量和方法,都改成类的实现。

追加public,并为Draw方法添加方法体。也就是图形的描述。

在该实例中,接口的每个实现类中都设置了带参数的构造方法为实现类中新增加的属性赋值,这样在创建实现类的实例时即可为相应的属性赋值。
    如果不使用构造方法为实现类中新增加的属性赋值,则需要先创建实现类的实例,并对其新增加的属性赋值,再将实现类的实例赋给接口的实例。

与 "IShape shapel = newRectangle( 10,20);" 等效的代码如下。

Reatangle rectangle = new Rectangle();rectangle.Length = 10;rectangle.Width = 20;IShape shape1 = rectangle;

为了简化代码,在接口的实现类中定义了新的属性,通常是通过实现类的构造方法为属性赋值的。

(而通过这个案例,可以看出。所谓的接口,其实就是将共有的部分提取出来封装成一个接口,然后再通过继承改写后,将缺少的部分追加上去。)

(就像长方形和圆形的继承类一样,它们都是图形,所以公有着的部分就是图形面积、坐标、颜色属性等没有争议的部分,然后将其整理出来,再通过实现不同的类,追加图形的不同部分。比如圆形和长方形的半径和长宽等。)

idea重写接口没有@override_【自学C#】|| 笔记 19 接口相关推荐

  1. java cloneable 接口_JDK源码阅读笔记-Cloneable接口

    JDK 版本:1.8 代码地址 1.前言 clone方法能方便的获得一个对象的拷贝,但其中也有些细节需要注意. 2.实现注意事项 2.1 要调用 clone 方法必须实现 Cloneable 接口 如 ...

  2. idea重写接口没有@override_乐字节|Java8核心实战-接口默认方法

    JAVA8已经发布很久,是自java5(2004年发布)之后Oracle发布的最重要的一个版本.其中包括语言.编译器.库.工具和JVM等诸多方面的新特性,对于国内外互联网公司来说,Java8是以后技术 ...

  3. idea重写接口没有@override_接口和抽象有什么区别?

    接口和抽象有什么区别? 接口和抽象是 Java 面向对象设计的两个基础机制. 接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到API 定义和实现分离的目的. 接口不能实例化, 接口不能包含任何 ...

  4. typescript学习笔记1 —— 接口(interface)

    typescript是微软出品的,javascript的超集.让javascript的写法很类似java,核心功能是让JavaScript这个弱类型的语言,增加类型检查,更适合编写企业级应用.之前的a ...

  5. 2接口详解_TS入门笔记2——TS接口进阶详解

    TS入门笔记--TS接口进阶详解 一.为什么需要接口? let obj:object; // 定义了一个只能保存对象的变量 // obj = 1; // obj = "123"; ...

  6. 第一章 计算机网络 5 分层结构/协议/接口/服务的概念 [计算机网络笔记]

    第一章 计算机网络 5 分层结构/协议/接口/服务的概念 本笔记参考书目: 计算机网络(第8版)谢希仁 2021王道计算机网络视频公开课 本节重点: 分层结构/协议/接口/服务 实体/对等实体 PCI ...

  7. EJB3.0学习笔记---多接口的时,实现类处理方法:

    EJB学习笔记--- 1.胖客户端:指的是定义的接口太多了,接口做的工作太多; 胖接口: 2.EJB实现类型的定义,用注解的方式,当一个EJBbean,实现了多个接口的时候, 需要用注解的方式指明哪一 ...

  8. 【java笔记】接口的定义,接口的使用

    java不支持多继承性,即一个类只能有一个父类.(单继承性) 为了解决单继承的缺点,java使用了接口 接口是一种引用数据类型,最重要的内容是抽象方法 (public) interface 接口名称{ ...

  9. C#学习笔记_14_接口命名空间

    14_接口&命名空间 接口 一系列规范 语法: 如果一个类的后面既有父类也有接口,那么一定是父类在前,接口靠后 一个类可以实现多个接口 规范:接口命名以大写字母 I 开头 接口中可以包含接口方 ...

最新文章

  1. 写给新手:2021版调参上分手册!
  2. 在leangoo中如何做好需求管理(研发效能)
  3. 【c语言】蓝桥杯入门训练 A+B问题
  4. PHP快速入门教程:for循环
  5. leetcode 10、Regular Expression Matching
  6. 2019年第十届蓝桥杯 C / C ++省赛 B 组真题题解
  7. python flask高级编程之restful_python Flask实现restful api service
  8. mocha chai mysql_Github MIT开源银行电子支付系统(ReactJS+Nodejs+Mysql)
  9. 3张经典人事管理模板,HR都直呼很好用
  10. java+jquery实现长轮询案例_网页实时聊天之js和jQuery实现ajax长轮询
  11. 计算机一级单元格填充,电脑Excel表格怎么对不连续的单元格进行批量填充
  12. 如何启用计算机的无线功能,笔记本电脑怎么开WiFi_笔记本电脑如何打开WIFI功能-win7之家...
  13. Android ListView异步获取网络图片
  14. SVN介绍及使用总结
  15. XMind ,石墨笔记, Effie ,你用什么应用来完成采编工作?
  16. java八大数据类型_java的八大基本数据类型分别是什么?
  17. 读书笔记:NOSQL 菜鸟教程
  18. 频谱聚类|拉普拉斯矩阵
  19. 长安奔奔Mini维修手册
  20. 易历知食c语言编程,易历知食_易历知食下载[2021官方最新版]易历知食安全下载_ 极速下载...

热门文章

  1. jacob 详解 语音_JAVA 实现Jacob语音播报
  2. pgsql merge方法
  3. Image.FrameDimensionsList 属性-----具体使用案例
  4. ubuntu - 14.04,配置GOPATH(GO语言开发代码存放目录)
  5. 在ASP.NET MVC应用程序中随机获取一个字符串
  6. IIS+PHP环境下出现HTTP 500服务器内部错误——请检查权限设置
  7. Android 灯光系统开发
  8. 【Python】随机种子 random/numpy/pytorch/pytorch.cuda
  9. 浅析HandlerThread
  10. Android对话框的高级设置《一》设置对话框按钮的图像和在内容文本中插入图像