C#接口(Interface)精讲

前言:接口的定义是指定一组函数成员而不实现成员的引用类型,其它类型和接口可以继承接口。更多关于C#隐式接口与显式接口的内容,请查看:浅谈C#隐式接口与显式接口

一、接口的概念

接口定义了所有类继承接口时应遵循的语法合同。接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。

  1. 接口定义了属性、方法和事件,这些都是接口的成员。接口只包含了成员的声明。成员的定义是派生类的责任。
  2. 接口提供了派生类应遵循的标准结构。
  3. 接口使得实现接口的类或结构在形式上保持一致。
  4. 抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。

二、接口示例讲解

1、创建接口

在这里插入图片描述
在这里插入图片描述
接口使用 interface 关键字声明,它与类的声明类似。接口声明默认是 public 的。下面是一个接口声明的实例:

interface Interface1 // interface 是关键字,后面的是接口名称
{
    void Run(); // 接口中的函数成员,不用实现,相当于一个抽象方法
}

以上代码定义了接口 Interface1。通常接口名称以 I 字母开头,这个接口只有一个方法 Run(),没有参数和返回值,当然我们可以按照需求设置参数和返回值。值得注意的是,该方法并没有具体的实现。

接下来,我们再创建一个接口,并让它继承上一个接口,操作步骤同上。

interface Interface2 : Interface1 // 继承另一个接口
{
    void Eat(); // 此接口独有的函数成员
}

2、实现接口

Program 类实现了Interface2 接口,接口的实现与类的继承语法格式类似。继承接口后,我们需要实现接口的方法,方法名必须与接口定义的方法名一致。如下:

class Program : Interface2 // Program类实现接口2,又因接口2继承接口1,故也实现接口1
{
    static void Main(string[] args)
    {
        Program p1 = new Program();
        p1.Run();
        p1.Eat();
        Console.ReadLine();
    }

    public void Run() // 实现接口1的方法
    {
        Console.WriteLine("实现接口,我会跑~");
    }

    public void Eat() // 实现接口2的方法
    {
        Console.WriteLine("实现接口,我会吃~");
    }
}

3、执行结果

在这里插入图片描述

三、对于接口的补充

由于类可以实现任意数量的接口,因此可能有多个接口成员有相同的签名和返回类型,例如:

interface IMyInter1
{
    void Print(string a);
}

interface IMyInter2
{
    void Print(string b);
}

对于上面的例子,有两种解决方法:

  1. 实现单个成员来满足所有包含重复成员的接口。
class MyClass : IMyInter1, IMyInter2
{
    public void Print(sting s)
    {
        Console.WriteLine("value is {0}",s);
    }    
}
  1. 创建显式接口成员实现,由接口名称加点号分隔符和成员名称组成。
class MyClass : IMyInter1, IMyInter2
{
    public void IMyInter1.Print(sting s)
    {
        Console.WriteLine("IMyInter1 value is {0}",s);
    }    

     public void IMyInter2.Print(sting s)
    {
        Console.WriteLine("IMyInter2 value is {0}",s);
    }    
}

四、关于接口的总结

  1. 定义一个接口在语法上跟定义一个抽象类完全相同,但不允许提供接口中任何成员的实现方式,一般情况下,接口只能包含方法,属性,索引器和事件的声明。
  2. 接口不能有构造函数,也不能有字段,接口也不允许运算符重载。
  3. 接口定义中不允许声明成员的修饰符,接口成员都是公有的。
  4. 接口可以彼此继承,其方式和类的继承方式相同。
  5. C#是单继承,接口是解决C#里面类可以同时继承多个基类的问题。

五、接口的一些注意事项

  1. 函数成员的声明不能有任何实现代码,并且在每个声明的主体后使用分号分隔。
  2. 通过接口可以实现多重继承,C#接口的成员不能有public、protected、internal、private等修饰符。原因很简单,接口里面的方法都需要由外面接口实现去实现方法体,那么其修饰符必然是public。C#接口中的成员默认是public的,java中是可以加public的。
  3. 接口成员不能有new、static、abstract、override、virtual修饰符。有一点要注意,当一个接口实现一个接口,这2个接口中有相同的方法时,可用new关键字隐藏父接口中的方法。
  4. 接口中只包含成员的签名,接口没有构造函数,所有不能直接使用new对接口进行实例化。接口中只能包含方法、属性、事件和索引的组合。接口一旦被实现,实现类必须实现接口中的所有成员,除非实现类本身是抽象类。
  5. 按照惯例,接口名称从大写的 I 开始,如 ITest。
  6. 如果类从基类继承并使用了接口,基类必须放在接口之前(只能有一个基类,接口可以有多个)。

六、接口和抽象类的区别

  1. 接口用于规范,抽象类用于共性。抽象类是类,所以只能被单继承,但是接口却可以一次实现多个。
  2. 接口中只能声明方法,属性,事件,索引器。而抽象类中可以有方法的实现,也可以定义非静态的类变量。
  3. 抽象类可以提供某些方法的部分实现,接口不可以。抽象类的实例是它的子类给出的。接口的实例是实现接口的类给出的。
  4. 在抽象类中加入一个方法,那么它的子类就同时有了这个方法。而在接口中加入新的方法,那么实现它的类就要重新编写(这就是为什么说接口是一个类的规范了)。
  5. 接口成员被定义为公共的,但抽象类的成员也可以是私有的、受保护的、内部的或受保护的内部成员(其中受保护的内部成员只能在应用程序的代码或派生类中访问)。此外接口不能包含字段、构造函数、析构函数、静态成员或常量。

猜你喜欢

转载自blog.csdn.net/qq_44034384/article/details/106671530