C# interface接口用法详解(附带实例)
由于 C# 中的类不支持多重继承,但是客观世界出现多重继承的情况又比较多。为了避免传统的多重继承给程序带来的复杂性等问题,同时保证多重继承带给程序员的诸多好处,C# 中提出了接口的概念,通过接口可以实现多重继承的功能。
接口提出了一种契约(或者叫规范),让使用接口的程序开发人员必须严格遵守接口提出的这种契约。
例如,在组装电脑时,主板与机箱之间就存在一种事先约定,不管什么型号或品牌的机箱,什么种类或品牌的主板,都必须遵照一定的标准来设计制造。因此在组装电脑时,电脑的零配件都可以安装在现今的大多数机箱上,接口就可以看作这种标准,它强制性地要求派生类必须实现接口约定的规范,以保证派生类必须拥有某些特性。
C# 中声明接口时,使用 interface 关键字,其语法格式如下:
接口可以继承其他接口,类可以通过其继承的基类(或接口)多次继承同一个接口。
接口具有以下特征:
例如,使用 interface 关键字定义一个 Information 接口,该接口中声明 Code 和 Name 两个属性,分别表示编号和名称;声明一个方法 ShowInfo(),用来输出信息,代码如下:
接口是通过类继承来实现的,一个类虽然只能继承一个基类,但可以继承任意多个接口。声明实现接口的类时,需要在继承列表中包含所实现的接口名称,多个接口之间用逗号(,)分隔。
【实例】创建一个 IPerson 接口,定义姓名、年龄两个属性,定义说话、工作两个行为,再创建 Student 类和 Teacher 类,两者继承 IPerson 接口并重写各自的属性和行为。创建两个人 peter 和 mike,让这两个人模拟上课的场景。代码如下:
第 11、13、27、31、39、41、55 和 59 行代码实现接口成员时都使用了public修饰符。这里需要注意的是,在 C# 中实现接口成员(显式接口成员实现除外)时,必须添加 public 修饰符,不能省略或者添加其他修饰符。
程序运行结果为:
在上面的实例中只继承了一个接口,接口还可以多重继承,使用多重继承时,要继承的接口之间用逗号(,)分隔,例如,继承 3 个接口,代码如下:
接口提出了一种契约(或者叫规范),让使用接口的程序开发人员必须严格遵守接口提出的这种契约。
例如,在组装电脑时,主板与机箱之间就存在一种事先约定,不管什么型号或品牌的机箱,什么种类或品牌的主板,都必须遵照一定的标准来设计制造。因此在组装电脑时,电脑的零配件都可以安装在现今的大多数机箱上,接口就可以看作这种标准,它强制性地要求派生类必须实现接口约定的规范,以保证派生类必须拥有某些特性。
C# 中声明接口时,使用 interface 关键字,其语法格式如下:
修饰符 interface 接口名称 : 继承的接口列表 { 接口内容; }
接口可以继承其他接口,类可以通过其继承的基类(或接口)多次继承同一个接口。
接口具有以下特征:
- 接口类似于抽象基类:继承接口的任何类型都必须实现接口的所有成员;
- 接口中不能包括构造函数,因此不能直接实例化接口;
- 接口可以包含属性、方法、索引器和事件;
- 接口中只能定义成员,不能实现成员;
- 接口中定义的成员不允许加访问修饰符,因为接口成员永远是公共的;
- 接口中的成员不能声明为虚拟或者静态。
例如,使用 interface 关键字定义一个 Information 接口,该接口中声明 Code 和 Name 两个属性,分别表示编号和名称;声明一个方法 ShowInfo(),用来输出信息,代码如下:
interface Information //定义接口 { string Code { get; set; } //编号属性及实现 string Name { get; set; } //名称属性及实现 void ShowInfo(); //用来输出信息 }注意,接口中的成员默认是公共的。因此,不允许加访问修饰符。
接口是通过类继承来实现的,一个类虽然只能继承一个基类,但可以继承任意多个接口。声明实现接口的类时,需要在继承列表中包含所实现的接口名称,多个接口之间用逗号(,)分隔。
【实例】创建一个 IPerson 接口,定义姓名、年龄两个属性,定义说话、工作两个行为,再创建 Student 类和 Teacher 类,两者继承 IPerson 接口并重写各自的属性和行为。创建两个人 peter 和 mike,让这两个人模拟上课的场景。代码如下:
interface IPerson //定义IPerson接口 { string Name { get; set; } //姓名属性 int Age { get; set; } //年龄属性 void Speak(); //说话行为 void Work(); //工作行为 } class Student : IPerson //定义学生类,继承自IPerson接口 { public string Name { get; set; } //实现Name属性 private int age; //定义age字段,用来表示年龄 public int Age { get { return age; } set { if (age > 0 && age < 120) //控制输入范围 { age = value; } } } public void Speak() //实现Speak方法 { Console.WriteLine(Name + ":老师好"); } public void Work() //实现Work方法 { Console.WriteLine(Name + "同学开始记笔记"); } } class Teacher : IPerson //定义老师类,继承自IPerson接口 { public string Name { get; set; } //实现Name属性 private int age; public int Age { get { return age; } set { if (age > 0 && age < 120) //控制输入范围 { age = value; } } } public void Speak() //实现Speak方法 { Console.WriteLine(Name + ":同学们好"); } public void Work() //实现Work方法 { Console.WriteLine(Name + "老师开始上课"); } } class Program { static void Main(string[] args) { //使用派生类对象创建接口数组 IPerson[] person = new IPerson[] { new Student(), new Teacher() }; person[0].Name = "peter"; person[0].Age = 20; person[1].Name = "mike"; person[1].Age = 40; person[0].Speak(); //学生的说话行为 person[1].Speak(); //老师的说话行为 Console.WriteLine(); person[1].Work(); //老师的工作环境 person[0].Work(); //学生的工作行为 Console.ReadLine(); } }程序中,第 3 行和第 4 行代码是定义接口中的属性,这里并不会自动实现属性,只是提供了 get 访问器和 set 访问器。因此在派生类中,需要实现这两个属性,在派生类中可以使用自动实现属性的方式实现这两个属性,例如,JHInfo 类中实现 Code 和 Name 属性的代码可以修改如下:
public string Name { get; set; } //姓名属性 public int Age { get; set; } //年龄属性
第 11、13、27、31、39、41、55 和 59 行代码实现接口成员时都使用了public修饰符。这里需要注意的是,在 C# 中实现接口成员(显式接口成员实现除外)时,必须添加 public 修饰符,不能省略或者添加其他修饰符。
程序运行结果为:
peter:老师好
mike:同学们好
mike老师开始上课
peter同学开始记笔记
在上面的实例中只继承了一个接口,接口还可以多重继承,使用多重继承时,要继承的接口之间用逗号(,)分隔,例如,继承 3 个接口,代码如下:
interface ITest1 { } interface ITest2 { } interface ITest3 { } class Test : ITest1, ITest2, ITest3 //继承3个接口,接口之间用逗号分隔 { }