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

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

一、介绍

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

对抽象类的继承才是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()
        {
        }
    }
时间: 2024-08-14 21:11:01

抽象类和接口的区别、使用和选择的相关文章

【翻译】JAVA中抽象类和接口的区别

不知道有没有人翻译过了,这篇是挺简单的,权当复习一遍内容吧. 很多常见的面试问题如"抽象类和接口有什么区别","你在什么时候用抽象类什么时候用接口".所以在这篇文章里面,我们会讨论一下这个话题. 在开始讨论它们的区别之前,我们先看看它们的介绍. Abstract class 抽象类 抽象类被用来抽象出子类的共同特征.它是不能被实例化的,它只能被子类继承作为超类使用.抽象类被用作它的子类下的层次结构创建模板(Abstract classes are used to c

[转]抽象类与接口的区别及应用

抽象类与接口的区别及应用 (本文由张洋提供) 抽象类(Abstract Class)与接口(Interface)是面向对象程序设计中两个重要的概念.由于两者在自身特性及应用方法上存在诸多相似性,如都不能实例化.都可以 被继承(严格来说对于接口应该叫做实现),这么一来,在许多人心中抽象类与接口的界限非常模糊,对何时该使用抽象类.何时该使用接口更是感到困惑. 本文的目的是通过对两者的讨论与比较,帮助读者认清抽象类与接口在思想本质及应用场合方面的区别,如能做到这一点,读者便可以得心应手地根据具体情况正

面向对象设计中抽象类与接口的区别

在OOD(面向对象设计)中,经常会用到抽象类或接口,[注:在C++中,没有接口的概念,只有抽象类:而在Java中两者都存在].而在使用过程中,也许会有不少人认为接口和抽象类差不多,然后就想当然地觉得可以相互完全替换.事实上,虽然他们有很多相似点,但也有很大差异. 1.抽象类与接口的出现条件 在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样.并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类.抽象类往往用来表征我们

抽象类和接口的区别。

学JAVA必须知道:抽象类与接口的区别 abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力. abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此很多开发者在进行抽象类定义时对于 abstract class和interface的选择显得比较随意. 其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对于问题领域本质的

Java中抽象类和接口的区别(abstract class VS interface)

前言:本文解决的问题 什么是抽象类 抽象类的应用场景 接口可以有方法实现吗 接口和抽象类的区别 1 什么是抽象类 在声明时含有关键字abstract就是抽象类,抽象类它可以看作具体类的一个模板,继承它的子类可以从抽象类中共享一些方法(可能是不完整的)和属性. A class which is declared with the abstract keyword is known as an abstract class in Java. It can have abstract and non-

抽象类和接口学习区别

最近复习了一些Java的基础知识,这里总结一下抽象类和接口的区别. 1. abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系.但是,一个类却可以实现多个interface. 2. 在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abst

抽象类和接口的区别——很深入的一篇文章

今天在IT学习者看到一篇螃蟹写的不错的文章,有些受用,拿来分享一下. 原文地址:http://www.itxxz.com/a/javashili/2014/0530/2.html abstract class和interface可谓是java中的双骄,既相辅相成又各司其职,相信一部分从业人员在没有掌握其中奥妙之前用的也就比较随意,java中为什么会出现这么模糊不清的一对呢?就从java的设计意图谈谈抽象类和接口的区别        平常我们总是说抽象类(abstract class)里可以写实现

java中抽象类与接口的区别

转自: http://blog.csdn.net/tp7309/article/details/10452445 二者的区别快忘得差不多了,从别处看到这文章感觉写的不错,正好复习复习,也给大家分享一下. 抽象类 abstract class 包含抽象方法的类,叫抽象类.而抽象的概念就是抽象出共同属性:成员变量和方法.所以抽象类可以有private等多种权限的成员变量和非abstract的成员方法.当然抽象方法是一定要有的. 抽象类是用于单一继承的,不能实例化.而继承类一定要实现抽象方法,因为抽象

C#抽象类与接口的区别

一.抽象类:      抽象类是特殊的类,只是不能被实例化(可以用派生类实例化基类对象):除此以外,具有类的其他特性:重要的是抽象类可以包括抽象方法(当然它可以有普通方法),这是普通类所不能的.抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须重写(覆盖)它们. 二.接口:      接口包含了一组方法的原型,接口是引用类型的,类似于类,和抽象类的相似之处有三点:       1.不能实例化:(参见MSDN显式接口实现)       2.包含未实现的方法声明:       3.派生类必须实

Java中抽象类和接口的区别(读书笔记)

Java的抽象类和接口 抽象类和接口是两个容易混淆的概念,但有一句话能很好地将这两者区分开来,即抽象类是事物的抽象,而接口是行为的抽象.抽象类抽象出来的是一类事物,事物中包含了一些固有的属性和行为,而接口更多的是提供固有属性行为之外的延伸行为.打个比方,可以把动物看成为抽象类,类中有一些固有属性,如身高体重,还有一些共有行为,如吃饭和睡觉,所有的动物都遵循着这些属性和行为.除此之外,有些动物还能飞,但并不是所有的动物都具有飞行这种能力,此时飞行只是事物的延伸功能,相当于一个接口. 一.抽象类 抽