1.接口的概念
1.1什么是接口?
接口是一种规范,是一种约束形式,其中只包括成员定义,不包含成员实现的内容。接口是一种能力,没有具体实现,像抽象方法一样,光说不做。
1.2接口怎么定义?
接口的定义与类的定义是类似的,只不过关键字不是class,而是interface。具体定义的特点如下:
- 接口成员不允许使用访问修饰符,所有接口成员都隐式为公共成员。
- 接口成员只能包括方法、属性、索引器、事件,本质都是方法,不能有字段,更不能包含方法体。
- 不能用关键字static、virtual、abstract或sealed来定义接口成员。
- 如果要隐藏从基接口中继承的成员,可以用new关键字来定义。
- 继承接口的类必须实现接口中所有成员,除非子类是抽象类。
需要注意的是接口名称一般以大写字母I开始,下面定义一个展示对象信息的接口:
interface IShowInfo
{
void ShowInfo();
}
1.3接口怎么实现?
让某个类继承上面定义的接口,实现接口中定义的打印信息的方法,就实现了这个接口。需要注意的是,接口的实现分为普通实现方法和显示实现方法两种。
下面这种是普通实现方法:
class Animal:IShowInfo
{
public void ShowInfo()
{
Console.WriteLine("我是动物类,实现了ShowInfo()接口。");
}
}
下面这种是显式实现方法:
class Animal1 : IShowInfo
{
void IShowInfo.ShowInfo()
{
Console.WriteLine("我是动物类,显式实现了ShowInfo()接口。");
}
}
为什么需要显式实现接口呢?假设一个类实现了多个接口,每个接口中都有一个定义相同的方法,我们用一个类来继承这两个接口,示例如下:
interface IShowInfo
{
void ShowInfo();
}
interface IShowInfo1
{
void ShowInfo();
}
class Animal1 : IShowInfo,IShowInfo1
{
void ShowInfo()
{
//尴尬了!!!!!
}
}
上述情况中,我们没法区分实现的是哪一个接口中的方法,普通实现方法就行不通了。所以,显式方法就是为了解决这个问题产生的。显式实现时采取 【接口名.方法名】方式就行了。如下所示:
class Animal1 : IShowInfo,IShowInfo1
{
void IShowInfo.ShowInfo()
{
Console.WriteLine("我是动物类,实现了IShowInfo接口。");
}
void IShowInfo1.ShowInfo()
{
Console.WriteLine("我是动物类,实现了IShowInfo1接口。");
}
}
1.4接口怎么调用?
- 普通方式实现接口和调用:
class Animal:IShowInfo
{
public void ShowInfo()
{
Console.WriteLine("我是动物类,实现了ShowInfo()接口。");
}
}
Animal p1 = new Animal();
p1.ShowInfo();
IShowInfo p2 = new Animal();
p2.ShowInfo();
结果如下:
我是动物类,实现了ShowInfo()接口。
我是动物类,实现了ShowInfo()接口。
- 显式实现接口和调用:
class Animal1 : IShowInfo
{
void IShowInfo.ShowInfo()
{
Console.WriteLine("我是动物类,显式实现了ShowInfo()接口。");
}
}
Animal1 p3 = new Animal1();
//p3.ShowInfo(); //error
(p3 as IShowInfo).ShowInfo();
IShowInfo p4 = new Animal1();
p4.ShowInfo();
结果如下:
我是动物类,显式方法实现了ShowInfo()接口。
我是动物类,显式方法实现了ShowInfo()接口。
可以发现,显式实现的接口方法在类中都是私有的,无法通过类的实例对象直接调用,需要把实例先转型成为对应的接口类型再进行调用。
1.4接口有什么作用?
接口的主要目的是为不相关的类提供通用的处理服务,实现多态。由于C#中只允许树形结构中的单继承,即一个类只能继承一个父类,所以接口是让一个类具有两个以上基类的唯一方式。一接口解决了类的多继承,又能使类继承后体积不那么庞大。
2.接口实现多态的例子
IShowInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3.接口_demo2
{
interface IShowInfo
{
void ShowInfo();
}
}
Car.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3.接口_demo2
{
abstract public class Car : IShowInfo
{
public string Name
{
get;
set;
}
public double Price
{
get;
set;
}
public abstract void ShowInfo();
}
public class Bieke : Car
{
public override void ShowInfo()
{
Console.WriteLine("我是别克车!");
}
}
public class Aodi : Car
{
public override void ShowInfo()
{
Console.WriteLine("我是奥迪车!");
}
}
}
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3.接口_demo2
{
public class Person : IShowInfo
{
public string Name
{
get;
set;
}
public int Age
{
get;
set;
}
public virtual void ShowInfo()
{
}
}
class American : Person
{
public override void ShowInfo()
{
Console.WriteLine("我是美国人....");
}
}
class Chinese : Person
{
public override void ShowInfo()
{
Console.WriteLine("我是中国人....");
}
}
class German : Person
{
public override void ShowInfo()
{
Console.WriteLine("我是德国人....");
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3.接口_demo2
{
class Program
{
static void Main(string[] args)
{
Person c = new Chinese();
c.ShowInfo();
Register(c);
Person a = new American();
Register(a);
Person g = new German();
Register(g);
Car aodi = new Aodi();
Register(aodi);
Car bieke = new Bieke();
Register(bieke);
Console.ReadKey();
}
public static void Register(IShowInfo i)
{
i.ShowInfo();
}
}
}
结果如下:
我是中国人....
我是中国人....
我是美国人....
我是德国人....
我是奥迪车!
我是别克车!
欢迎关注我的公众号。