JAVA抽象类(包含abstract、interface)

来源:互联网 发布:网上打麻将软件 编辑:程序博客网 时间:2024/06/11 18:56

抽象类 是对一系列看上去不同,但是本质上相同的具体概念的抽象。

在语法层面,

Java语言对于abstract class和interface给出了不同的定义方式:

abstract class方式定义:

abstract class Demo{     int num1;     abstract int num2;     abstract void method1();     abstract void method2();}


interface 方式定义:

interface Demo{     static final int num;     void method1();     interface method2();}
interface 中只能有 静态的、不能修改的 数据成员(static final),但是在interface中一般不定义数据成员
interface 中所有成员方法都是abstract的。interface是一种特殊形式的abstract class.


首先,abstract class在java语言中表示 “一种继承关系”(即,需要用到extends关键字),一个类只能单继承(java不支持多继承),但可 实现多个interface(即,需要用到implements关键字)。PS:为了弥补无法多继承的缺陷。


其次,abstract class可以赋予方法 默认行为,但interface中,方法不能拥有默认行为。

如果不能再抽象类中定义默认行为,就会导致 “同样的方法实现” 出现在该抽象类的每一个派生类中,造成代码重复,同样不利于以后维护。

设计理念层面,


abstract class在应用时,必须保证“is-a”(父子继承关系B is a A.);而interface应用时,并不要求interface的实现者 与 interface存在"is-a"关系,只需实现interface定义的契约即可(是一种“like-a”关系)。


案例:抽象一个Door类,用以Security_Door类继承。(abstract class和interface两种方式对比)。

abstract class Door{       abstract void open();       abstract void close();}

interface Door{       void open();       void close();}

现在,Security_Door需要一个门铃功能。有三种方案:

            1、简单的在Door抽象类中添加alarm()方法:

        abstract class Door        {             abstract void open();             abstract void close();             abstract void alarm();        }
        interface Door        {             void open();             void close();             void alarm();        }
              这样定义Door,导致 将Door的固有行为  与  另外一个功能Alarm行为  混在一起。

           从而导致,有些仅依赖于Door固有行为 的模块,贅余上Alarm行为。若Alarm行为改变,导致仅依赖Door固有行为的模块也随之强迫、无用的 改变。

          这也正是ISP(接口分离原则)所否定的!


          2、open()、close()和alarm()属于 两个不同的 概念,根据ISP原则,应该把它们 分别定义 两个抽象类中。

                    理论上可以:

                            (1)  这两个概念都用 abstract class 方式定义。(java不支持多继承,故不可行!)

                            (2)  这两个概念都使用 interface 方式定义。     (先确定继承者的本质,Door Or Alarm。从而知道谁是主体,谁是附属,明确显示出设计意图。显然这种方式doubleinterface不能表明)

                            (3)  一个用abstract class定义,一个用interface定义。(Security_Door  extends Door  implements Alarm合理!)

                abstract class Door                {                    abstract void open();                    abstract void close();                }                interface Alarm                {                    void alarm();                }                class Security_Door extends Door implements Alarm                {                    void open();                    void close();                    void alarm();                }




附注:

       1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。

       2.在abstract class 中可以有自己的数据成员(only public, protected, private, static, final, transient & volatile),而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员)。

       3.在abstract class 中成员方法可以有  abstract方法(不能有方法体)  和  非abstract方法(可以有方法体),继承abstract class时必须实现  所有abstract方法;而在interface中成员方法(不能有方法体)(only public & abstract,声明成public还是abstract没有区别,所以直接不用public/abstract修饰即可,因此其默认是public还是abstract也没有探究必要了。个人猜测,用public、abstract或者public abstract 修饰是同一效果,总之,肯定是abstract的,因为不允许有方法体),实现interface时,必须实现 所有成员方法

  4.abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。 


  5.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

  6.抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。 

  7.接口中的方法默认都是 public,abstract 类型的。(有歧义)


ISP(Interface Segregation Principle 接口隔离原则)

一、定义

讲接口隔离原则,它有两种定义:

第一种定义: Clients should not beforced to depend upon interfaces that they don't use.

客户端不应该依赖它不需用的接口。

第二种定义:The dependency of oneclass to another one should depend on the smallest possible interface。

类间的依赖关系应该建立在最小的接口上。

二、解释

第一种定义客户端不应该依赖它不需要接口,那依赖什么?依赖它需要的接口,客户端需要什么接口就提供什么接口,把不需要的接口剔除掉,那就需要对接口进行细化,保证其纯洁性;

第二个定义,类间的依赖关系应该建立在最小的接口上,它要求是最小的接口,也是要求接口细化,接口纯洁,与第一个定义如出一辙,只是一个事物的两种不同描述。





0 0