人生最可悲的事情,莫过于胸怀大志,却又虚度光阴。 ​​​​

《Thinking In Java》读书笔记 第9章 接口

2014.07.10

9.1 抽象类和抽象方法

Java提供了一个叫做抽象方法的机制,这种方法是不完整的,仅有声明而没有方法体。 下面是抽象方法声明所采用的语法:

abstract void f();

包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的,否则,编译器就会报错。

如果从一个抽象类继承,并想创建该心累的对象,那么就必须为基类中的所有抽象方法提供方法定义。如果不这样做,那么导出类变也是抽象类,且编译器将会强制我们用abstract关键字来限定这个类。

我们也可能会创建一个没有任何抽象方法的抽象类。

9.2 接口

interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类的类型,来实现某种类似多重继承的特性。

9.3 完全解耦

9.4 Java的多重继承

public interface CanFight {
    void fight();
}
public interface CanSwim {
    void swim();
}
public interface CanFly {
    void fly();
}
public class ActionCharacter {
    public void fight(){}
}
public class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly {
    //CanFight接口和ActionCharacter类中的fight()方法的特征签名一样
    public void swim() {}

    public void fly() {}
}
public class Adventure {
    public static void t(CanFight x){x.fight();}
    public static void u(CanSwim x){x.swim();}
    public static void v(CanFly x){x.fly();}
    public static void w(ActionCharacter x){x.fight();}

    public static void main(String[] args) {
        Hero hero = new Hero();
        t(hero);
        u(hero);
        v(hero);
        w(hero);
    }
}

9.5 通过继承来扩展接口

通过继承,可以很容易地在接口中添加新的方法声明,可以通过继承在新接口中组合数个接口。这两种情况可以获得新的接口。

public interface Monster {
    void menace();
}
public interface DangerousMonster extends Monster  {
    void destory();
}
public interface Lethal {
    void kill();
}
public class DragonZilla implements DangerousMonster {
    public void menace() {}
    public void destory() {}
}
//一般情况下,只可以将extends用于单一类,但是可以引用多个基类接口。
public interface Vampire extends DangerousMonster,Lethal {
    void drinkBlood();
}
public class VeryBadVampire implements Vampire {
    public void menace() {}
    public void destory() {}
    public void kill() {}
    public void drinkBlood() {}
}
public class HorrorShow {
    static void u(Monster b) {
        b.menace();
    }
    static void v(DangerousMonster d) {
        d.menace();
        d.destory();
    }
    static void w(Lethal l) {
        l.kill();
    }
    public static void main(String[] args) {
        DangerousMonster barney = new DragonZilla();
        u(barney);
        v(barney);
        Vampire vlad = new VeryBadVampire();
        u(vlad);
        v(vlad);
        w(vlad);
    }
}

9.5.1 组合接口时的名字冲突

实现多重继承时,相同的方法不会有什么问题,但是如果它们的签名或返回类型不同,又会怎么样呢?

public interface I1 {
    void f();
}
public interface I2 {
    int f(int i);
}
public interface I3 {
    int f();
}
public class C {
    public int f(){
        return 1;
    }
}
//重载
public class C2 implements I1, I2 {
    public void f() {}
    public int f(int i) {
        return 1;
    }
}
//重载
public class C3 extends C implements I2 {
    public int f(int i) {
        return 0;
    }
}
public class C4 extends C implements I3 {
}
//下面代码会出错
//public class I4 extends I1,I3 {
//    public void f() {
//
//    }
//}

9.6 适配接口

9.7 接口中的域

因为你放入接口中的任何域都自动是staticfinal的,所以接口就成为了一种很便捷的用来创建常量组的工具。

9.7.1 初始化接口中的域

在接口中定义的域不能是空final,但是可以被非常量表达式初始化。

既然域是static的,它们就可以在类第一次被加载时初始化,这发生在任何域首次被访问时。

public interface RanVals {
    Random RAND = new Random(47);
    int RANDOM_INT = RAND.nextInt(10);
    long RANDOM_LONG = RAND.nextLong() * 10;
    float RANDOM_FLOAT = RAND.nextLong() * 10;
    double RANDOM_DOUBLE = RAND.nextDouble() * 10;
}

9.8 嵌套接口

接口可以嵌套在类或其他接口中。

9.9 接口与工厂