接口

接口属于引用类型,包含一个或多个方法,而不包含实现,表示能够做到的功能。

接口命名使用I开头,通常使用形容词。

接口的定义

语法

[可见性修饰符] interface 接口名称
{
    接口成员
}

可见性修饰符:

public:表示接口可以在任何地方被访问

internal:表示接口可以在程序集内部被访问。

private:用于嵌套类型。表示接口可以在嵌套类型外被访问。

通常,接口都是公共的,非公共的接口外部无法使用,也就失去的接口的意义。

接口的成员

接口可以包含方法,属性,索引器,事件。这些其实都是方法。

接口中的成员不包含任何可见性修饰符,都是公共的。

方法

语法:

返回值类型 方法名称(参数列表);

属性

语法:

返回值类型 属性名称{get;set;}

get和set可以只包含一个。

索引器

语法:

返回值类型 索引器名称 this(参数列表){get;set;}

get和set可以只包含一个。

事件

语法:

event 委托类型 事件名称;

接口的继承

接口可以继承自其他借口

语法:

[可见性修饰符] inteface 接口名称: 接口1,接口2
{

}

接口的继承

public interface ICollection
{
    public void Add(object item);
    public void Remove(object item);
    public int Count {get;}
}

public interface IList : ICollection
{
    public object this[int index]{get;set;}
}

实现接口

类或结构可以实现接口,实现接口要求类或结构包含接口的所有成员。

语法:

class 类名: 接口1,接口2
{

}

struct 结构名: 接口1,接口2
{

}

实现接口

public interface ICanBark
{
    void Bark();
}

public class Dog : ICanBark
{
	public void Bark()
	{
		Console.WriteLine("汪");
	}
}

一个类实现了一个接口,就可以用一个接口类型的变量来保存类。

ICanBark bark = new Dog();
bark.Bark();

显示接口实现

通过包含接口的所有成员实现的接口,是隐式接口实现。

通过在成员名称前加上接口名称的方式,是显式实现。

public interface ICanBark
{
    void Bark();
}

public class Dog : ICanBark
{
	 void ICanBark.Bark()
	{
		Console.WriteLine("汪");
	}
}

通过显示接口实现的方法是没有可见性修饰符的。

通过显示接口实现的类,不能直接调用接口成员,只能够通过接口进行调用。

ICanBark canBark = new Dog();
canBark.Bark();//ok

Dog dog = new Dog();
dog.Bark();//编译错误

实际上,显示实现的成员是私有的,名称是接口全名.成员名,只有通过接口的引用才可以访问。

值类型在转换成接口时有装箱的开销。

显式接口实现的作用

如果有两个接口,有成员名称一致,通过隐式实现的话就无法区分,只能通过显式接口实现可以区分两者。

同时实现

如果一个接口的成员是显式接口实现,同时包含隐式实现,在通过类型调用时,使用的是隐式实现,使用接口调用时,调用的是显式实现。这是隐式实现不是接口的实现。

一个接口的成员可以有的是显式实现,有的是隐式实现。

基础库中的显式接口实现

实现IEnumerable<T>接口的类型.这是由于同时有泛型和非泛型的GetEnumerator方法,要加以区分。

基本类型如Int32,CharIConvertible.

使用建议

在区分成员名称时使用。

其他情况不建议使用显式接口实现。

如果一定要使用,并同时包含隐式实现,显式实现请调用隐式实现。

接口的作用

接口表达的是一种能力,实现同一接口的类型拥有同样的能力。

IComparable接口说明类型有比较大小的能力,实现了这个接口的类型,就可以做大小排序,而不必知道具体类型。

IEnumerable接口说明类型可以提供迭代器,可以通过迭代器访问类型的所有元素,而不必知道类型的实际存储的结构。

通过接口,一段代码可以只和接口相关,而不必和某个具体类型相关,增强了代码复用,减少了类型之间的关联。