【问题标题】:Subclassing Inner Class from Outer Class versus other Inner Class从外部类与其他内部类子类化内部类
【发布时间】:2009-10-19 15:52:54
【问题描述】:

我很困惑为什么允许这样做

public class Foo {
    class Bar extends Foo {
    }
}

但这是不允许的

public class Foo {
    class Bar extends Foo {
    }

    class Fooey extends Bar {
    }
}

编译器在调用超类型构造函数之前通知它不能引用 Fooey.this。

这是允许的

public class Foo {
    static class Bar extends Foo {
    }

    class Fooey extends Bar {
    }
}

这里发生了什么?我在哪里可以找到有关内部类继承如何工作的更多信息?

编辑我遇到了两个相当糟糕的想法;内部类扩展外部类,内部类扩展其他静态内部类。我不确定到底发生了什么以及我应该如何重构它。我最终只是抽出内部类并将它们封装在外部类中。

【问题讨论】:

  • 看看这个问题,很确定这重复了它:stackoverflow.com/questions/70324/…
  • 不是骗子(至少不是那个)。
  • 拥有要扩展的类的外部实例有什么用?
  • @Jorn,我在重构旧代码时遇到了这两个问题。是的,在生产环境中发生了可怕的事情。

标签: java inheritance inner-classes


【解决方案1】:

首先:不要做这种事情。这是邪恶的。真的,Java 1.1 的规定应该更加严格,IMO。

对于 Foo.Fooey 构造函数中使用哪个 this 存在混淆。外部 this (Foo.this) 可以工作。但是实际的thisFoo 但它不能传递给超级构造函数,因为在超级构造函数返回之前使用this 的规则(并且除了具有与内部实例相同的外部实例之外) )。由于this的使用限制,超类“((Bar)this).this$0”(IIRC)上的外部this也无法访问。

解决方案是明确的。在我的书中,显式通常是一件好事(除非它成为样板)。

public class Foo {
    class Bar extends Foo {

    }

    class Fooey extends Bar {
        Fooey() {
            Foo.this.super();
        }
    }
}

更好的是,不要让内部类扩展它自己的外部类,或扩展任何内部类。

【讨论】:

  • +1 表示您的第一句话。如果你必须显式地创建一个构造函数,因为默认构造函数没有编译,我会说你做错了(设计明智)。
  • 汤姆,谢谢你的回答。我想到了两个相当糟糕的想法。内部类扩展外部类,内部类扩展其他静态内部类。我不确定发生了什么。
【解决方案2】:

我猜 JLS 和这个问题的答案是一个起点

Java inner class and static nested class

Inner Classes and Enclosing Instances

【讨论】:

    【解决方案3】:

    Tom Hawtin 的回答是正确的。

    还可以查看java puzzler。示例章节包含此案例和其他一些您可能想查看的“有趣”案例。

    【讨论】:

      【解决方案4】:

      (还不能发表评论 - 我需要 50 个代表)

      我也很困惑这是允许的。外部类的(非静态)内部类实际上是该外部类的成员。阅读:内部对象是其外部对象的成员。 (顺便说一句,每个外部对象必须拥有一个内部对象,但这不是重点。)

      我喜欢使用的类比是:让Car 成为外部类,让Wheel 成为内部类。 Car 的每个实例都必须并且确实有至少一个 Wheel 实例作为成员。

      现在,内部类扩展外部类在概念上没有意义。我想不出任何现实世界的情况需要一个对象既是成员又是另一个对象的类型。集合论者会想起 Axiom of Regularity 及其后果。

      这样想:让Honda 扩展Car,让Honda 成为嵌套在Car 中的内部类。你在这里说的是每个Honda 对象是一个 Car 对象(duh),每个Car 对象都有一个 Honda 对象。这些陈述中只有一个有意义,但在 Java 中两者都允许为真。

      或者回到前面的类比,你不应该让Wheel 扩展Car,因为Wheel成为Car,并且根据定义必须 另一个Wheel,顺便说一下是一个 Car,所以必须有一个 Wheel 和永远永远阿门。构造Car 对象会导致嵌套对象的无限循环。

      我很不高兴这是合法的并且不会产生编译时错误。

      【讨论】:

      • 想象一下,如果您在生产代码中看到它,您会多么沮丧!
      • 如果 Honda 扩展 Car,它确实意味着每个 Car 对象都有一个 Honda 对象。
      • @RAY:是的,但是如果 Honda 嵌套在 Car(也就是 Car 的“成员”)中,那么它确实意味着每个 Car 对象都有一个 Honda 对象。
      • 不正确。如果 Honda 是 Car 的内部类,则 Car 对象不一定有 Honda 对象。另一方面,Honda 对象必须具有对父 Car 对象的引用。您需要能够区分成员类和成员变量。
      • 明白。仅当 Car 类包含以下行时,我是否假设 Car 对象具有 Honda 对象是正确的:private Honda accord;
      猜你喜欢
      • 2017-06-30
      • 2023-01-24
      • 2014-01-26
      • 1970-01-01
      • 1970-01-01
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多