《Beginning Java 7》 - 7 - abstract class 抽象类 和 interface 接口

1. 抽象类:

为什么用抽象类:

  一些 generic 的类本身并没有现实意义,所以不需要被实例化。比如动物,自然界没有动物这个物种,但却有无数的继承自动物的物种,那么动物本身可以是一个抽象类。

抽象类使用规则:

  • 抽象类不可以被创建,不能有实例。
  • 抽象类不可以是 final 的,因为 final 类不能被继承,那么抽象类就没任何意义了。
  • 抽象类可以包含任意可见性的属性。
  • 可以包含非抽象方法,但非抽象方法必须实现(必须有函数体)。
  • 可以不包含抽象方法。
  • 抽象方法只能声明,不能实现。
  • 抽象方法在子类中必须被实现,除非子类本身也是抽象的。
  • 抽象方法不可以是 private 的,而是 public 或 protected 的。
  • 抽象方法不可以是 static 的。

 

2. 接口:

接口使用规则:

  • 接口里的方法默认而且必须是 public abstract 的,只能声明,不可以实现,所以也不可以是 static 的。
  • 接口被 implements 时,所有方法都必须被实现,并且改变可见性会报错(必须是 public 的)。
  • 接口里可以声明属性,但必须初始化,因为接口属性默认而且必须是 public static final 的。
  • 接口命名经常用 XXXable,比如 Adjustable, Callable, Comparable, Cloneable, Iterable, Runnable, 和 Serializable.
  • 接口和类一样默认是 friendly 的,只能在同一个包中使用。所以常常需要声明为 public 的。
  • 接口可以声明为 abstract 的,但由于它本来就是 abstract 的,所以没有任何意义。
  • 接口里可以什么都不写,这样的接口叫 marker interface 标记接口 或 tagged interface 标签接口。比如 Cloneable。
  • 接口和继承类似的一点是,可以把一个实现了某接口的类的实例强制转换为此接口的类型。比如 Thread 实现了 Runnable,所以 Thread 可以被强制转换成 Runnable 类型。
    Thread t = new Thread();
    Runnable r = (Runnable) t;
  •  接口可以多重继承。我们都知道一个类可以实现多个接口,但和类不同的一点是,一个接口可以继承多个接口。
    interface A{}
    interface B{}
    interface C extends A,B {}

    这是没有问题的。

什么情况下使用接口:

  使用接口可以提高编码的灵活性,便于协作,修改和测试。接口用来赋予一种新的能力。比如我们有一些图形的类,长方形,圆形,三角形。我们想给他们添加一个方法,叫 draw() ,用来画出图形。此时我们就可以让这些图形 implements 一个 interface,我们可以取名叫 Drawable,里面声明一个 draw() 方法,这样所有图形都能画了。

 

3. 接口和抽象类有哪些区别和联系:

联系:

  • 接口是一种特殊的抽象类。两者都不能被创建(实例化)。
  • 接口和抽象类可以混合使用(比如抽象类可以实现一个接口,但接口不能继承一个抽象类)。
  • 接口和抽象类的抽象方法都不可以是 static 的,因为抽象方法只有声明没有实现,不能被调用。

区别:

  • 抽象类的属性可以是任意可见性的,但接口的属性只能是 public static final 的。
  • 抽象类里面可以有非抽象方法(有实现),但接口里面只能包含抽象方法(只有声明)。
  • 抽象类的方法可以是 默认 friendly, public 或 protected 的,但不能是 private 的。接口的方法只能是 public abstract 的。
  • 抽象类和普通类一样,不支持多重继承。而接口可以多重继承。
  • 抽象类是继承关系,是 is a 的关系。比如大象是动物。而接口只是赋予能力。一个经典案例是,我们定义一个门,门是可以开和关的。那么我们可以有:
    abstract class Door {
        abstract void open();
        abstract void close();
    }
    
    interface Door {
        void open();
        void close();
    }
    看起来并无太大区别,至少都能用。但我们如果想让门加上报警功能变成报警门呢。我们考虑三种方案:门和报警器都是抽象类,都是接口,或一个抽象类一个接口。应该如何设计呢?第一个方案马上就抛弃了,因为多重继承是不可能的。第二种方案不能够准确形象的表达报警门和门和报警器直接的关系。所以正确的方式是,报警门是门的一种,所以门是抽象类,报警门继承门并实现报警器接口。
    abstract class Door{
        abstract void open();
        abstract void close();
    }
    interface Alarm{
        void alarm();
    }
    class Alarm Door extends Door implements Alarm{
        void open(){…}
        void close(){…}
        void alarm(){…}
    }
posted @ 2013-12-27 09:44  davesuen  阅读(272)  评论(0编辑  收藏  举报