Java中接口的菱形继承问题?

新手上路,请多包涵

有一个交通工具接口 Vehicle,包含 getSpeed 方法
然后有船只接口 Boat 继承自交通工具接口,包含 sail 方法,
有飞机接口 Plane 继承自交通工具借口,包含 fly 方法。
现在有一个又可以飞又可以航行的交通工具 BoatPlane,它要实现 Boat 和 Plane 两个接口

请看这样的代码:

public class Test {

    public static void main(String[] args) {
        Boat boat = new BoatPlane();
        boat.sail();
        System.out.println(boat.getSpeed());    // 输出1

        Plane plane = (Plane) boat;
        plane.fly();
        System.out.println(plane.getSpeed());   // 输出2
    }
}

interface Vehicle {
    int getSpeed();
}

interface Boat extends Vehicle {
    void sail();
}

interface Plane extends Vehicle {
    void fly();
}

class BoatPlane implements Boat, Plane {

    @Override
    public int getSpeed() {
        return 10;
    }

    @Override
    public void sail() {
        System.out.println("sail()");
    }

    @Override
    public void fly() {
        System.out.println("fly()");
    }
}

现在,输出 1 和输出 2 的结果是一样的。
但是,我希望 Boat 和 Plane 在调用 getSpeed 时结果不一样,请问如何做到?

我在 StackOverFlow 中查到,Java 中不存在菱形继承导致的问题,因为具有相同方法签名的两个方法会被合并成一个。
这样 Java 就似乎不能通过接口来实现这样的功能了。
那么,Java 中有什么相对优雅的方式来实现呢?

阅读 3.9k
2 个回答

如果有两个速度,实际上是有一个内蕴状态的,如果希望分开,不如直接定义成getFlySpeed和getSailSpeed

自己想了一下确实没想出来怎么实现,网上找了一下,java8之后好像接口函数可以有实现了,但导致双继承的实现类必须自己override掉对应的接口函数,实现类的行为没法根据单一接口类型产生区别。

public class Test {
    static interface top {
        default int face() {
            return 1;
        }
    }

    static interface middle1 extends top {
        @Override
        default int face() {
            return 0;
        }
    }

    static interface middle2 extends top {
        @Override
        default int face() {
            return 2;
        }
    }

    static class bottom implements middle1,middle2 {
        @Override
        public int face() {
            return 0;
        }
    }

    public static void main(String[] args) {

        Test.middle2 b = new Test.bottom();
        System.out.println(b.face());//只能是0


    }
}

另外一个思路是用组合,把曲线救国,把多重继承变成内部类分别继承,如:

public class Son {    
class Father_son extends Father {     }     
class Mother_son extends Mother {     }     
public void father() {        (new Father_son()).output();    }     
public void mother() {        (new Mother_son()).output();    }}

那么实现类就和多接口不是直接实现的关系,需要那个接口的行为就直接调用相应的内部实现类。这样我感觉有点用组合替代继承的味道。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏