抽象类
抽象类是使用 abstract
关键字标记的类。与非抽象类相反,它可能包含抽象 - 无实现 - 方法。但是,在没有抽象方法的情况下创建抽象类是有效的。
无法实例化抽象类。只要子类也是抽象的,或者实现超类标记为抽象的所有方法,它就可以是子类(扩展)。
抽象类的一个例子:
public abstract class Component {
private int x, y;
public setPosition(int x, int y) {
this.x = x;
this.y = y;
}
public abstract void render();
}
当类具有至少一个抽象方法时,必须将其标记为抽象。抽象方法是一种没有实现的方法。可以在具有实现的抽象类中声明其他方法,以便为任何子类提供公共代码。
尝试实例化此类将提供编译错误:
//error: Component is abstract; cannot be instantiated
Component myComponent = new Component();
但是,这个类扩展了 Component
,并为其所有抽象方法提供了实现,并且可以实例化。
public class Button extends Component {
@Override
public void render() {
//render a button
}
}
public class TextBox extends Component {
@Override
public void render() {
//render a textbox
}
}
继承类的实例也可以转换为父类(正常继承),并且在调用抽象方法时它们提供多态效果。
Component myButton = new Button();
Component myTextBox = new TextBox();
myButton.render(); //renders a button
myTextBox.render(); //renders a text box
抽象类与接口
抽象类和接口都提供了一种定义方法签名的方法,同时需要扩展/实现类来提供实现。
抽象类和接口之间有两个主要区别:
- 类只能扩展单个类,但可以实现许多接口。
- 抽象类可以包含实例(非
static
)字段,但接口可能只包含static
字段。
Version < Java SE 8
在接口中声明的方法不能包含实现,因此在提供称为抽象方法的实现的其他方法时,使用抽象类。
Version >= Java SE 8
Java 8 允许接口包含默认方法 ,通常使用接口的其他方法实现 ,使得接口和抽象类在这方面同样强大。
抽象类的匿名子类
为方便起见,java 允许实例化抽象类的子类的匿名实例,这些实例在创建新对象时提供抽象方法的实现。使用上面的示例,这可能如下所示:
Component myAnonymousComponent = new Component() {
@Override
public void render() {
// render a quick 1-time use component
}
}