lsekfe 发表于 2023-3-28 15:01:01

浅谈Java不支持多继承的原因

首先,思考这么一种场景,假如现在A类继承了B类和C类,并且B类和C类中,都存在test()方法,那么当A类对象调用test()方法时,该调用B类的test()呢?还是C类的test()呢?是没有答案的,所以Java中不允许多继承。
  但是,Java中接口是可以多继承的,比如:
  public interface A {
      void test();
  }
  public interface B {
      void test();
  }
  public interface C extends A, B{


  }


  为什么接口可以?
  因为都是A、B、C都是接口,就算A、B两个接口中都定义了test方法,因为接口中只是声明了方法,并没有真正实现方法,所以对于C接口而言并不会照成困扰,对于C接口而言它只是继承了同一个test()方法的声明而已,在使用时需要C接口的实现类来实现这个test()方法就可以了。
  public class C1 implements C{
      public void test() {
        System.out.println("hello Hoeller");
      }
  }


  那么接口中不是有default方法吗?那不是也可以在接口中来实现方法吗?
  我们直接来测试一下:
  public interface A {
      default void test() {
        System.out.println("a");
      }
  }
  public interface B {
      default void test() {
        System.out.println("b");
      }
  }
  public interface C extends A, B{
  }


  此时C接口会编译报错,报错信息为:
  com.hoeller.C inherits unrelated defaults for test() from types com.hoeller.A and com.hoeller.B

  翻不翻译都无所谓了,反正就是报错了,表示C接口不能同时继承两个接口中default方法test()。
  如果你问,那为什么C++中可以支持多继承,那得解释菱形继承、虚继承,本文就不分析了(因为我也不知道)。

V587g 发表于 2023-3-28 17:13:03

为什么Java不支持多重继承, 可以考虑以下两点:

1) 第一个原因围绕钻石形继承问题产生的歧义,考虑一个类 A 有 foo() 方法, 然后 B 和 C 派生自 A, 并且有自己的 foo() 实现,现在 D 类使用多个继承派生自 B 和C,如果我们只引用 foo(), 编译器将无法决定它应该调用哪个 foo()。这也称为 Diamond 问题,因为这个继承方案的结构类似于菱形.

即使我们删除钻石的顶部 A 类并允许多重继承,我们也将看到这个问题含糊性的一面。如果你把这个理由告诉面试官,他会问为什么 C++ 可以支持多重继承而 Java不行。嗯,在这种情况下,我会试着向他解释我下面给出的第二个原因,它不是因为技术难度, 而是更多的可维护和更清晰的设计是驱动因素, 虽然这只能由 Java 言语设计师确认,我们只是推测。维基百科链接有一些很好的解释,说明在使用多重继承时,由于钻石问题,不同的语言地址问题是如何产生的。

2) 对我来说第二个也是更有说服力的理由是,多重继承确实使设计复杂化并在强制转换、构造函数链接等过程中产生问题。假设你需要多重继承的情况并不多,简单起见,明智的决定是省略它。此外,Java 可以通过使用接口支持单继承来避免这种歧义。由于接口只有方法声明而且没有提供任何实现,因此只有一个特定方法的实现,因此不会有任何歧义。
页: [1]
查看完整版本: 浅谈Java不支持多继承的原因