【问题标题】:Multiple layer inheritance - Java多层继承 - Java
【发布时间】:2012-06-24 13:44:51
【问题描述】:

如果a类扩展b类,b类扩展c类,a 继承自 cb?如果是这样,如果两者之间发生冲突,是否存在错误或是否会覆盖另一个(如果是,是哪一个)?

如果标题不合适,请重命名问题。

编辑:我所说的冲突是这样的:

class c {
   int foo;
   //Stuff
}
class b extends c {
   String foo;
   //Stuff
}
class a extends b {
   //Stuff
}

a.foo 是字符串还是整数?

另一个编辑:据我所知,这里的继承有点像 CSS - 规则设置得越接近,它的优先级就越高(例如内联样式覆盖样式表)。这是考虑这一点的好方法,还是有很大不同?

【问题讨论】:

  • 切线,这就是为什么publicprotected 变量被许多人认为是糟糕的形式。
  • @TonyEnnis - 两者都不是;我只是想将两个“库”类扩展为一个。
  • 如果存在真正的冲突,代码将无法编译。您的帖子中没有“冲突”,只是一个简单的名称隐藏问题,您可以自己测试。 StackOverflow is not a research assistant。投反对票。
  • 我在谈论更高级的案例,以及是否会发生任何变化。你想让我生成每一个这样的冲突案例吗?我敢肯定,为此而编写的程序可能会有一些自己的类冲突:P

标签: java oop class inheritance


【解决方案1】:

如果bc 中都存在某些东西,a 将继承b 使用的任何一个。

【讨论】:

  • +1,但如果你在结尾加上“...等等”就完美了。
【解决方案2】:

是的,a 继承自 b 和 c。我看不出在这种情况下怎么会发生冲突,因为 b 的方法覆盖对 a 有效。您可能会想到来自多重继承冲突的diamond problem,但那是当您有两个不同的父母时,而不是两个父母,其中一个父母是另一个父母的父母。

您可能会遇到接口的“软”菱形问题,其中两个方法具有相同的签名,但一个方法的规则与另一个方法的规则不匹配。由于两个接口都没有实现它们的方法,所以不存在编译问题(据我所知),只是逻辑问题。

编辑啊,我已经看到您对变量的编辑,我同意 Jimpanzee 对此的回应。这当然很容易测试:

public class Test3 {
   public static void main(String[] args) {
      MyA myA = new MyA();
      System.out.println("foo := " + myA.foo);
   }
}

class MyC {
   public int foo = 3;
   //Stuff
}
class MyB extends MyC {
   public String foo = "foo";
   //Stuff
}

class MyA extends MyB {

}

【讨论】:

    【解决方案3】:

    嗯,规则如下。

    1. 任何子类都将继承最接近其层次结构的位置。所以 a 将从 b 获取所有内容。因为继承堆栈上的所有内容都将在 b 之前可用。因为 b 已经从其继承层次结构中继承了所有内容。

    2. 其次,如果 b 覆盖任何东西(实例变量/方法),那么 a 将看到覆盖的版本。所以在你的情况下 a 会得到 String foo。

    【讨论】:

    • 您能为此添加 JLS 的链接吗?
    • 嗯..这就是继承的关键..如果您发现任何冲突的问题,我会很高兴
    • 不,我同意你的看法。我只是为了原始海报的利益而建议一个 JLS 链接。 1+ 票。
    • 不,除了 Java 中的方法之外,没有任何东西可以覆盖。其他一切都是继承而来的,不管同名与否。
    • @Marko...技术上叫实例变量隐藏
    【解决方案4】:

    This answer 有一个更好的例子,并指出做这种事情被认为是不好的做法。 (例如,Eclipse 会给你一个警告。)稍微扩展你的代码:

    class c {
       int foo = 42;
       //Stuff
    }
    class b extends c {
       String foo = "foostr";
       //Stuff
    }
    class a extends b {
       //Stuff
    }
    class Main{
       public static void main(String[] args){
          a mya = new a();
          System.out.println(mya.foo);
       }
    }
    

    运行java Main 打印foostr

    【讨论】:

      【解决方案5】:

      在 Java 中,只有方法可以被覆盖。其他一切都只是继承,只有命名空间冲突的问题,但一切仍然可以访问。在您的示例中,foos 都可以在 A 中访问(我已经更正了类名以使其符合强大的 Java 命名约定):

      class C {
        int foo;
        //Stuff
      }
      class B extends C {
        String foo;
        //Stuff
      }
      class A extends B {
        String x = ((B)this).foo;
        int i = ((C)this).foo;
      }
      

      【讨论】:

        【解决方案6】:

        是的,它继承自 c 和 b。 为了防止/避免冲突,Java 支持单一层次模型(不同于其他 OOP 语言,如允许多类继承模型的 C++)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-04-06
          • 2014-03-16
          • 1970-01-01
          • 2016-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多