在面向对象的编程思维下,一切都是抽象而来的对象。所有的设计与抽象都为了高内聚低耦合这一目的。
接口多用作对行为的抽象描述。为了区别抽象类,继承等这些设计理念我们举例说明:
动物:设计为抽象类,将所有动物的共同特征抽象出来,这里我们之定义公共属性Food(所有动物都是要吃东西的吧,这一点没有争议吧!)
public abstract class Animal
{
public string Food{get;set;}
}
鸟类:继承自“动物”类,这里也只定义一个属性,这个属性是一个对象“翅膀”
(同样,鸟类都是有翅膀的,这个也没有例外吧。顺便问个问题,所有鸟都下蛋吗?)
这里特别强调一下,对于类的设计,是基于实例的抽象,也就是所有实例都具有的特性才可以被封装到类中。通俗的讲就是所有鸟都具有的特征才能被放到“鸟”这一类中。但是随着设计的复杂化,对象的模糊化,这一简单的原则却常常被忽略。
public class Bird:Animal
{
public Wing Egg { get; set; }
}
public class Wing
{
}
飞行:飞行这一特征是脱离“鸟”这种类的约束的,并不是所有鸟都会飞,会飞的也不一定是鸟,比如蝙蝠,飞机,超人之类…
飞行这一特性有两个要素可以抽象出来,飞行的“速度”和飞行的“方式”
//接口
public interface IFly
{
string Speed();
string Type(string type);
}
鹦鹉:鸟类的一种,可以飞行,所以它继承了“鸟”类和“飞行”接口,又有自己的特有属性“年龄”
//鹦鹉
public class Parrot:Bird,IFly
{
//非接口属性
public string Age { get; set; }
//实现接口属性(显式)
public string Speed()
{
return "2-3";
}
//实现接口属性(隐式)
string IFly.Type(string type)
{
return "飞行方式:" + type;
}
}
企鹅:鸟类的一种,但不能飞行,所以只能继承“鸟”这一类
//企鹅
public class Penguin:Bird
{ }
OK,准备工作完毕开始演示与解释:
Parrot poly = new Parrot();
poly.Food = "薯条";
//继承抽象类的属性
Response.Write("poly吃的是:"+poly.Food+"<br>");
实例化一只叫“poly”的鹦鹉,它的食物是薯条。
//接口的实现
Response.Write("poly的飞行速度是:" + poly.Speed() + "千米/小时 <br>");
但是,如果要调用“poly.Type("poly的飞行方式")”就会报错
IFly flyOfParrot = new Parrot();
flyOfParrot.Speed();
flyOfParrot.Type("扇翅膀,短距离飞行");
接口的隐式实现只能采用上面的方式调用。
接口的用法大体就这么多,有的同学也想来点准确具体的描述,那就有点晦涩了,不过我们也不能拒绝这种要求,深入了解概念也是一种认真的方式。
接口定义:用来定义程序的协定。
在上面的实例中,“飞行”这一接口如果对外公开,那么不管是什么的飞行,飞行的那两个特性都是确定的,具体的实现方式交给继承他的类来处理,就算以后添加了“飞碟”我们的接口依然可用,我们的规范依然很好的保持着。
接口的成员:属性,方法,事件,索引器。
接口可以被类和结构体继承。
接口成员不能有修饰符 public,private,protected,virtual,接口成员都是public 类型。
接口成员不能包含实现方式,具体实现都由继承它的类定义。
继承类定义接口成员的实现方式是需类型和参数形式完全相同。
在继承类中接口的隐式实现成员不会被包含在继承类的实例中。
继承类中接口的隐式成员只有通过接口的继承类实例化定义后才能被使用。
接口成员在类的继承中实现覆盖与类的继承相同,都是用new关键字。