• 5
  • 新人请关照

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 中有什么相对优雅的方式来实现呢?

阅读 358
评论
    2 个回答
    • 11.4k

    如果有两个速度,实际上是有一个内蕴状态的,如果希望分开,不如直接定义成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();    }}

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

        撰写回答

        登录后参与交流、获取后续更新提醒