Java编程思想拾遗(8) 接口

抽象类

如果我们只有一个像Instrument这样的抽象类,那么该类的对象几乎没有任何意义,我们创建抽象类是希望通过这个通用接口操纵一系列类。因此,Instrument只是表示了一个接口,没有具体的实现内容,创建一个Instrument对象没有什么意义,并且我们可能还想阻止使用者这样做,通过让Instrument中的所有方都产生错误就可以实现这个目的,但是这样做会讲错误信息延迟到运行时才获得,并且需要在客户端进行可靠、详尽的测试,所以最好在编译时捕获这些问题。

为此,Java提供了一个叫做抽象方法的机制,这种方法是不完整的,仅有声明而没有方法体,如果一个抽象类不完整,那么当我们试图产生该类的对象时,由于为抽象类创建对象时不安全的,所以我们会从编译器那里得到一条出错信息。

接口

interface关键字使抽象的概念更向前迈进了一步,一个接口表示:“所有实现了该特定接口的类看起来都像这样”,因此任何使用某特定接口的代码都知道可以调用该接口的哪些方法,而且仅需知道这些。接口被用来建立类与类之间的协议

  • 接口里的方法默认都是public,毕竟协议是需要公开暴露的。
  • 接口里的域默认都是static的,在多接口实现场景可以区分同名域属于哪个接口。
  • 接口里的域默认都是final的,如果域可以修改,那么就没有继承意义,接口要的就是协议化,另外一个角度:因为是static的所以一个接口的域只能有一个实例,所以需要用的话只能在接口先初始化,对于实现类对象没有任何修改的意义。
  • 因为枚举enum的出现,所以用接口单纯描述域就显得过时了。

多重继承

接口不仅仅只是一种更纯粹形式的抽象类,它的目标比这更高,因为接口是根本没有任何具体实现的,也没有任何与接口相关的存储,因此也就无法阻止多个接口的组合。

在导出类中,不强制要求有一个是抽象的或具体的基类,如果要从一个非接口的类继承,那么只能从一个类去继承,其余的基元素必须使接口。可以继承任意多个接口,并可以向上转型为每个接口,因为每个接口都是一个独立的类型。

interface CanFight {
    void fight();
}

interface CanSwim {
    void swim();
}

interface CanFly() {
    void fly();
}

class ActionCharacter {
    public void fight() {}
}

class Hero extends ActionCharater implements CanFight, CanSwim, CanFly {
    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 h = new Hero();
        t(h);
        u(h);
        v(h);
        w(h);
    }
}
复制代码

注意,CanFight接口与ActionCharater类中的fight()方法的特征签名是一样的,而且在Hero中并没有提供fight()的定义,其定义就是来自于ActionCharater,但如果两者返回值类型不同,编译器会执行拒绝。

多重继承是可以对原有类库接口进行适配的重要方式。

接口本身可以进行多重继承。

interface Monster {
    void menace();
}
interface DangerousMonster extends Monster {
    void destroy();
}
interface Lethal {
    void kill();
}
interface Vampire extends DangerousMonster, Lethal {
    void drinkBlood();
}
复制代码

嵌套接口

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

  • 作用于接口的各种规则,特别是所有的接口元素都必须是public,因此嵌套在另一个接口中的接口自动就是public的,而不能声明为private的,除非内部刚好有对应的实现类和对这个private接口的public访问方法。
  • 当实现某个接口时,并不需要实现嵌套在其内部的任何接口,此时嵌套接口相当于内部成员变量,未必要被实现,可以单独实现外部接口或者嵌套接口。

我们应该使用接口还是抽象类?恰当的原则应该是优先选择类而不是接口,从类开始,如果接口的必需性变得非常明确,那么就进行重构。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享