gpt4 book ai didi

java - 为什么外部类不能扩展内部类?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:08:19 28 4
gpt4 key购买 nike

为什么我不能这样做/是否有解决方法来实现此目的:

package myPackage;

public class A {
public class B {

}
}

package myPackage;  

import myPackage.A.B;

public class C extends B {

}

package myPackage;

public class Main {
public static void main(String[] args) {
A myA = new A();
C myC = myA.new C();
}
}

两个编译错误是

  1. public class C extends B 上,由于某些中间构造函数调用,类型 A 的封闭实例不可用

  2. C myC = myA.new C(); 上,A.C 无法解析为类型

坦率地说,我认为概念上的想法是合理的:我想创建 B 的子类,这样当我为 A 创建 B 时,我可以选择使其具有 B 中的功能或 C 中的功能。

想要的四种解决方法/解决方案,以及我不想要它们的原因:

  1. “解决方案:将 C 放在 A 中。”我不想要这个,因为如果我不能修改 A.java 的代码怎么办(有些应用程序有这个限制)?如果 A 是另一个 API 的一部分怎么办?然后我必须为 C 创建一个新文件,就像我在此处所做的那样。

  2. “解决方案:将 C 放在扩展 A 的类 D 中。”我不想要这个,因为 C 被限制为只能在 D 类型的实例上实例化。我想创建一个扩展 B 的类,它可以在 A 类型的所有实例上实例化(有需要这个的应用程序)。因此,我需要 C 不包含在另一个类中,就像我在此处所做的那样。

  3. (作为问题编辑添加 - 请参阅 JoshuaTaylor 对代码示例的回答)“解决方案:使 B 静态化。”我不想要这个,因为如果 B 中的功能需要访问其封闭的 A 实例怎么办(有些应用程序需要这个)?因此,我需要 B 不是静态的,就像我在这里所做的那样。 (第二个问题编辑:您可以使 B 静态并让它的构造函数接受它的封闭实例,将它保存在一个 protected 变量中以供其子级访问,但这不如 RealSkeptic 接受的答案优雅)

    <
  4. 已删除。请参阅底部的编辑。

因此,如果您的回答建议我执行上述操作之一,那么它不是这个问题的答案,即使它可能对其他人有用。

如果您的回答是“这只是 Java 语言的一个缺陷,您根本不能完成那个概念性想法”,这是一个不错的答案,您应该发布它。不过只是一个警告:如果你错了,我会推迟将你的答案标记为已接受。如果这是你的答案,如果你能解释为什么对语言有这种限制(因为这是这个问题的标题),我将不胜感激。

感谢您提供的所有帮助。

编辑:JoshuaTaylor 的回答提出了一个有效选项:您可以扩展 B anonymously并避免像 RealSkeptic 接受的答案那样编写构造函数。我最初放弃了这个想法,因为它不允许您通过“A.this”访问 C 的 A 封闭实例。但是,从那以后我了解到 C 没有 A 的封闭实例,除非它在 ​​A 的定义中明确定义为嵌套类。所以请注意:下面的任何解决方案都不允许您通过在 C 的方法中写入“A.this”来访问包含 B 的 C 祖先的 A 的封闭实例。类只能使用“.this”来访问它们的类型专门嵌套在。但是,如果 B 具有访问 A 的封闭实例的功能,则需要通过 JoshuaTaylor 方法的匿名类或通过 RealSkeptic 方法的任何其他类。

最佳答案

嗯,这可以做到,但你必须记住,每个构造函数都需要显式或隐式地调用其 super 构造函数。这就是为什么您会收到 “由于某些中间构造函数调用,类型 A 的封闭实例不可用” 错误的原因。 C 的无参数构造函数试图隐式调用 B 的无参数构造函数,如果没有 A.

因此,您将 C 修改为:

public class C extends B {
public C(A enclosing) {
enclosing.super();
}
}

然后您可以使用以下方法创建一个新的C:

A myA = new A();
C myC = new C(myA);

评论中问题的答案

  • @Andi Turner 问:

    If you are explicitly passing in an A to the constructor of C, can't C now be static, and have A as a "plain old" member variable in C on which you invoke the required methods?

    需要注意的是C既不是static也不是内部类。它是一个扩展内部类 B 的独立公共(public)类。C 的作者可能不知道类 B 的实现,因此它不知道将使用 A 的哪些方法,也无法访问任何私有(private)成员A 的,因为 C 不是 A 的成员。但是 B 是,并且 B 需要 A 实例。另一种方法是组合而不是继承(其中 C 持有一个 B 实例并将操作委托(delegate)给它),但是如果它想创建 B 实例而不是将其传递到内部,它仍然需要一个 A 实例,尽管它会使用 enclosing.new B 而不是 enclosing.super

  • @rajuGT 问:

    Is C is an individual entity? if so, why does it need A object? and what is the association between myA and myC in this case?

    是的,C 是一个单独的实体。它自己的任何方法都不需要 A。但是,如果它试图从 B 调用(或继承但不覆盖)涉及访问 A 的方法 - 那么 B 的实现需要 A。当然,形式上,B 的任何实例甚至都需要引用 A如果它实际上没有使用它。 myAmyC 之间的关联是 myAmyC 的直接封闭实例到 B。该术语取自 section 8.1.3 of the JLS :

    For every superclass S of C which is itself a direct inner class of a class or interface SO, there is an instance of SO associated with i, known as the immediately enclosing instance of i with respect to S. The immediately enclosing instance of an object with respect to its class' direct superclass, if any, is determined when the superclass constructor is invoked via an explicit constructor invocation statement (§8.8.7.1)

此用法的官方引用

这种用法被称为限定父类(super class)构造函数调用语句,并在JLS, section 8.8.7.1 - Explicit Constructor Invocations 中提到。 .

Superclass constructor invocations begin with either the keyword super (possibly prefaced with explicit type arguments) or a Primary expression or an ExpressionName. They are used to invoke a constructor of the direct superclass. They are further divided:

  • Unqualified superclass constructor invocations begin with the keyword super (possibly prefaced with explicit type arguments).

  • Qualified superclass constructor invocations begin with a Primary expression or an ExpressionName. They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.

在该部分的末尾,您可以找到显式构造函数调用语句的示例,包括这种用法。

关于java - 为什么外部类不能扩展内部类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33026474/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com