9.1抽象类和抽象方法
在应用继承时,基类的很多方法是子类的通用接口,其本身并无实际意义。创建基类对象没有意义,我们甚至需要组织用户这么做。但是,如果用户这么做了,我们将在运行时才会发现错误。为了使错误信息在编译时就可以被捕获,我们可以将基类定义为抽象类。
抽象的关键字为abstract,java提过了抽象方法机制,这种方法是不完整的;仅有声明没有方法体。如:
abstract void f();
包含抽象方法的类叫抽象类。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的。如果一个从抽象类继承,并想创建为该新类创建对象,那么就必须为基类中的所有抽象方法提供方法定义。否则该类依然是抽象的,编译器会强制你加上abstract关键字。
9.2接口
接口的关键字为interface,这个关键字产生一个完全抽象的类。接口只提供方法的声明,而未提供方法体。接口被用来建立类与类之间的协议。
关键接口就像创建类,只是需要用interface替换class关键字。可以在interface前添加public关键字(仅限与该接口在与其同名的文件中,这也与类类似)。如果不添加public关键字,则只有包访问权限。此外,接口也可以包含域,但是这些域是隐式的是static 和 final的,同时接口中的域自动是public的。
接口中定义的方法必须是public的,即使没有明确显示定义,他们默认也是public的。
9.4java中的多重继承
java中的继承是单继承的,但是如果需要从多个地方继承接口,可以选择用接口来实现。implement关键字可以继承多个接口。下面是一个例子。
interface CanFight{ void fight(); //默认为public } interface CanSwim{ void swim(); } interface CanFly{ void fly(); } class ActionCharacter{ public void fight(){} } class Hero extends ActionCharacter implements CanFight, CanFly, CanSwim{ //fight方法从ActionCharacter继承而来。 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 x = new Hero(); t(x); u(x); v(x); w(x); } }
Hero组合具体类和接口时,具体类必须放在前面,后面跟着的才是接口。(否则编译器会报错)。
这里带来一个问题,我们应该使用接口还是抽象类?如果要创建不带任何方法定义和成员变量的基类,那么应该选择接口而不是抽象类。事实上,如果知道某食物应该成为一个基类,我们第一选择应该是使他成为一个接口。
9.5接口继承可以用来扩展接口
9.8嵌套接口
几口可以嵌套在类或其他接口中。特别要注意的是,当实现某个接口时,并不需要实现嵌套在其内部的任何接口。而且private接口不能在定义它的类之外被实现。
在进行设计时,恰当的原则应该是优先选择类而不是接口。从类开始,如果接口的必需性变得非常明确,那么就进行重构。接口是一种重要的工具,但是容易被滥用。