抽象类与接口
目录
- 抽象类
- 先从继承开始
- 继承无法解决的问题
- 为什么抽象类不能实例化对象
- 接口
- 抽象方法的问题
- 使用接口解决
- 总结
- 被继承的普通类---抽象类(对部分方法抽象)---接口(全部由抽象方法组成)
抽象类
- 先从继承开始
继承是为了代码的复用。
现在有 MallardDuck (绿头鸭),RocketDuck (火箭鸭),RubberDuck (橡皮鸭)。
三种鸭子都能在水上漂流 float,而且漂浮的方式都是一样的。这样可以定义一个父类。三种鸭子通过继承获得漂流的方法,好处是不用每个鸭子都要再写一遍 float 方法。
class Duck{
public void float(){
System.out.println("All ducks can float");
}
}
class MallardDuck extends Duck{}
class RocketDuck extends Duck{}
class RubberDuck extends Duck{}
- 继承无法解决的问题
不同的是三种鸭子的飞行方式,这时候就不能简单的在Duck类中实现fly方法。(当然可以在每个子类中覆写fly方法,此时父类中的fly方法就没有必要具体实现)解决办法是把飞行这个动作抽象为fly方法。然后由每个子类具体实现fly方法。这时候 Duck 就成了抽象类。注意要使用 abstract 关键字声明类名。 - 为什么抽象类不能实例化对象?
因为抽象类没有完整的描述一个类(fly方法没有具体实现)。
abstract class Duck{
public void float(){
System.out.println("All ducks can float");
}
public abstract void fly();
}
class MallardDuck extends Duck{
public void fly(){
System.out.println("I am flying with wings");
}
}
class RocketDuck extends Duck{
public void fly(){
System.out.println("I am flying with rockets");
}
}
class RubberDuck extends Duck{
public void fly(){
System.out.println("I cannot fly");
}
}
接口
-
抽象方法无法解决的问题
假设现在有个RedheadDuck, 它的飞行方式和MallardDuck相同。这时候又要重新写一遍 MallardDuck 的 fly 方法。如果有成千上万的类需要重写的话,那后果可想而知。 -
使用接口解决
- 定义接口存放fly方法
- 为每个具体的fly方法实现接口
- 子类实例化时传入具体飞行方法
interface FlyBehavior{
fly();
}
class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("I am flying with wings");
}
}
class FlyWithRockets implements FlyBehavior{
public void fly(){
System.out.println("I am flying with rockets");
}
}
class FlyNoWay implements FlyBehavior{
public void fly(){
System.out.println("I cannot fly");
}
}
现在重新写Duck类
class Duck {
FlyBehavior flyBehavior;
public Duck(FlyBehavior fb){
flyBehavior = fb;
}
public void performFly() {
flyBehavior.fly();
}
public void float() {
System.out.println("All ducks can float");
}
}
class MallardDuck extends Duck{
public MallardDuck(){
super(new FlyWithWings());
}
}
class RocketDuck extends Duck{
public RocketDuck(){
super(new FlyWithRockets());
}
}
class RubberDuck extends Duck{
public RubberDuck(){
super(new FlyNoWay());
}
}
class RedheadDuck extends Duck{
public RedheadDuck(){
super(new FlyWithWings());
}
}
现在开始测试
public class DuckTest {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
Duck rocket = new RocketDuck();
Duck rubber = new RubberDuck();
Duck redhead = new RedheadDuck();
mallard.performFly();
rocket.performFly();
rubber.performFly();
redhead.performFly();
}
}
I am flying with wings
I am flying with rockets
I cannot fly
I am flying with wings
这样只需要在定义具体类的时候传入飞行的方式就行了。即使有再多的类也可以因为所有的飞行方式都已经实现了。
References
Three passions, simple but overwhelmingly strong, have governed my life: the longing for love, the search for knowledge, and unbearable pity for the suffering of mankind