星空网 > 软件开发 > ASP.net

抽象类和接口的区别、使用和选择

不谈抽象类可以有实现等语法糖的问题,本文主要讲在语义层面抽象类和接口的本质区别、以及使用以及选择。

 一、介绍

抽象类,首先是个类,类是对现实世界中对象的建模模型,抽象类是对类整体的抽象描述,包含方法,以及属性。接口是对类某特性行为的抽象。

对抽象类的继承才是Is-A的关系,对接口的实现,则是“有没有”的关系。比如鸟和飞机都有飞行这个特性,这个时候可以把飞行这个特性设计为接口:IFly。然后再让Airplane和Bird实现IFly这个接口,这样Airplane和Bird则拥有了飞行这个属性。

接下来飞机可能有多种,鸟也有多种,他们飞行的方法完全不同,这样就可以把Airplan和Bird设计成抽象类,让不同的飞机和鸟进行继承。

类图:

抽象类和接口的区别、使用和选择

代码:

public abstract class AbstractAirplane : IFly{  public void Fly()  {    this.PrepareToFly();    this.Step1();    this.Step2();  }  private void PrepareToFly()  {  }  protected abstract void Step1();  protected abstract void Step2();}

public abstract class AbstractBird : IFly{  public void Fly()  {    this.PrepareToFly();    this.Step1();    this.Step2();  }  private void PrepareToFly()  {  }  protected abstract void Step1();  protected abstract void Step2();}

在上面的设计中,IFly定义了飞的行为:

  1. AbstractAirplane是实现了该行为,并且定义了飞机飞行的模型,PrepareToFly,Step1,Step2。由于不同飞机的Step1和Step2各不相同,所以定义为Abstract,让子类自己实现
  2. AbstractBird实现了该行为,并且定义了鸟的飞行模型,PrepareToFly,Step1,Step2。由于不同鸟的Step1和Step2各不相同,所以定义为Abstract,让子类自己实现

上面的例子可以看出,抽象类一种模版式的设计,接口是一种行为规范。

模版式设计:如果共用部分要修改,比如上图中的PrepareToFly,则只需要修改共用部分,不需要修改其他,对于抽象类来说,如果要增加方法,可以直接操作父类,子类可以不知情。

行为规范:如果接口要变更,实现这个接口的类都要修改。

二、接口与抽象类的选择

现实中门有两个方法Open(), Close(),定义方式分别如下所示:

使用接口方式定义门:

 interface IDoor  {    void Open();    void Close();  }

 

使用抽象类方式定义门:

 abstract class AbstractDoor  {    public abstract void Open();    public abstract void Close();  }

 

 

刚开始一切都OK,但是随着用户需求的发展,要给门加入报警(Alarm)功能,现在怎么做?

  1. 把Alarm放入AbstractDoor中,这样所有继承自这个类的门都会有Alarm功能,但是并不是所有的门都有报警功能,这样违反了liskov替换原则
  2. 把Alarm放入IDoor接口中,需要Alarm的门都实现这个接口,那么需要报警的门得同时实现Open和Close功能,其实有些报警的门不一定需要Open和Close功能,

分析:

从上面可以看出,Open和Close是一个门的固有属性,Alarm属于门的延伸附加行为,最好的解决办法是针对Alarm单独设计一个接口:

public interface IAlarm   {    void Alarm();  }

 

普通门的实现:

 public class NormalDoor : AbstractDoor  {    public override void Open()    {    }    public override void Close()    {    }  }

 

具有报警功能的门的实现:

 public class AlarmDoor : AbstractDoor,IAlarm  {    public override void Open()    {    }    public override void Close()    {    }    public void Alarm()    {    }  }

 

只能报警的设备的实现:

 public class AlarmDevice : IAlarm  {    public void Alarm()    {    }  }




原标题:抽象类和接口的区别、使用和选择

关键词:接口

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

Fashion:https://www.goluckyvip.com/tag/560.html
利润计算公式:https://www.goluckyvip.com/tag/5600.html
英国交通标志:https://www.goluckyvip.com/tag/56000.html
负面反馈:https://www.goluckyvip.com/tag/5601.html
澳大利亚的标志性建筑物是什么:https://www.goluckyvip.com/tag/56010.html
德国标志性建筑:https://www.goluckyvip.com/tag/56011.html
2022世界杯门票如何买?:https://www.vstour.cn/a/363182.html
沈阳到本溪的距离有多远?(详细路线及交通方式):https://www.vstour.cn/a/363183.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流