接口概述
与 类
一样,在接口
中可以定义一个和多个方法、属性 、索引指示器和事件。但与类
不同的是,接口
中仅仅是它们的声明
,并不提供实现
。因此接口是函数成员声明的集合。如果类或结构从一个接口派生,则这个类或结构负责实现该接口中所声明的所有成员。一个接口可以从多个接口继承,而一个类或结构可以实现多个接口。由于 C#
语言不支持多继承,因此,如果某个类需要继承多个类的行为时,只能使用多个接口加以说明。
对接口的理解:
- 接口只有声明,没有实现,由继承该接口的类或者结构实现。
- C#的类只支持单继承,采用
接口
变相实现了多继承。 - 接口更多的是一种
规范约束
,要求继承该接口的类或者结构必须对接口成员进行实现。
接口声明
接口声明是一种类型声明,它定义了一种新的接口类型。接口声明格式如下:
属性 接口修饰符 interface 接口名:基接口{接口体}
其中,关键字interface、接口名和接口体时必须的,其它项是可选的。接口修饰符可以是new、public、protected、nternal和private。例子:
1 | public interface IExample { |
声明接口时,需注意以下内容:
- 接口成员只能是方法、属性、索引指示器和事件,不能是常量、域、操作符、构造函数或析构函数,不能包含任何静态成员。
- 接口成员声明不能包含任何修饰符,接口成员默认访问方式是
public
。
接口的继承
类似于类的继承性,接口也有继承性。派生接口继承了基接口中的函数成员说明。接口允许多继承,一个派生接口可以没有基接口,也可以有多个基接口。在接口声明的冒号后列出被继承的接口名字,多个接口名之间用分号分割。例子:
1 | using System; |
上面的例子中,接口ITextBox
和IListBox
都从接口IControl
中继承,也就继承了接口 IControl
的Paint
方法。接口IComboBox
从接口ITextBox
和IListBox
中继承,因此它应该继承了接口ITextBox
的SetText
方法和IListBox
的SetItems
方法,还有IControl
的Paint
方法。
类对接口的实现
前面已经说过,接口定义不包括函数成员的实现部分。继承该接口的类或结构应实现这些函数成员。这里主要讲述通过类来实现接口。类实现接口的本质是,用接口规定类应实现那些函数成员。用类来实现接口时,接口的名称必须包含在类声明中的基类列表中。
加入定义一个描述个人情况的类Person,从类Person可以派生出其它类,例如:工人类、公务员类、医生类等。这些类有一些共有的方法和属性,例如工资属性。一般希望所有派生类访问工资属性时用同样变量名。该属性定义在类Person中不合适,因为有些人无工资,如小孩。如定义一个类作为基类,包含工资属性,但C#不支持多继承。可行的办法是使用接口,在接口中声明工资属性。工人类、公务员类、医生类等都必须实现该接口,也就保证了它们访问工资属性时用同样变量名。例子如下:
1 | using System; |
抽象类和接口比较
抽象类 | 接口 |
---|---|
相同点 | |
可以被继承 | 可以被继承 |
可以有方法的声明 | 可以有方法的声明 |
不可以被实例化 | 不可以被实例化 |
子类必须实现基类的方法除非子类是抽象类 | 子类必须实现基类的方法除非子类是抽象类 |
以下为不同点 | |
一个类只能直接继承一个类(包括抽象类) | 一个类可以直接继承多个接口 |
是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性; | 是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性 |
是一个不完整的类,需要进一步细化 | 是一个行为规范。 |
抽象基类可以定义字段、属性、方法实现。 | 接口只能定义属性、索引器、事件、和方法声明,不能包含字段。 |
更多的是定义在一系列紧密相关的类间 | 大多数是关系疏松但都实现某一功能的类中 |
只能作用于引用类型 | 可以作用于值类型和引用类型 |
抽象类既可以定义规则,还可能提供已实现的成员。 | 只能定义抽象规则 |