如何使外部类继承自内部类?

时间:2011-04-16 09:51:01

标签: java inner-classes

我怎样才能做出像这样的工作:

class Outer {
  int some_member;

  abstract class InnerBase {
    abstract void method();
  }
}

class OuterExtendsInner extends Outer.InnerBase {
  OuterExtendsInner(Outer o) { o.super(); }
  void method() {
    // How do I use some_member here?
    // Writing Outer.this.some_member -> error about Outer not being an enclosing class
    // Writing just some_member -> no-go, either
  }
}

解决方法是在InnerBase中有一个返回Outer.this并从派生类调用THAT的方法,但还有另一种方法吗?

我主要想从外部扩展InnerBase以获得更好的代码组织,但我可以将所有派生类移动到外部。

7 个答案:

答案 0 :(得分:3)

您可以在OuterExtendsInner中执行此操作:

class OuterExtendsInner extends Outer.InnerBase {
    Outer o;

    OuterExtendsInner(Outer o) {
        o.super();
        this.o = o;
    }

    void method() {
        // now you can reference o.some_member
        int x = o.some_member;
    }
}

答案 1 :(得分:3)

此处的问题是将InnerBaseOuter相关联的合成字段是私有字段。因此,我们只能从InnerBase内访问外部对象,或者如果某个方法或字段提供对同一对象的引用。

答案 2 :(得分:1)

答案是:你不能,因为它会破坏封装。只有InnerBase可以访问Outer的属性,而不能访问OuterExtendsInner。它不是直接继承。 InnerBase不继承Outer。

答案 3 :(得分:1)

我没有尝试过WhiteFang34的回答。它可能会奏效,但我不清楚......

如果你真的想要在外部类中定义内部类的扩展,那么最自然的事情就是将它定义为另一个外部扩展外部类的内部类的扩展,如下所示:

class Outer {
  int some_member;

  abstract class InnerBase {
    abstract void method();
  }
}

class OuterExtendsOuter extends Outer {
  class InnerExtendsInner extends Outer.InnerBase {
    void method() {
       System.out.println(some_member);
    }
  }
}

我实际上也没有运行此代码,但它应该可以运行。

<强>更新

基于评论主题,我现在已经编译并运行了上面的代码和WhiteFang34的代码。

两者实际上都有效,但正如PaŭloEbermann的评论中所指出的,两者都在实例化的内部类中创建了两个外部副本。

我将赞成Paŭlo的答案,并且主张不要试图通过任何一种策略来做到这一点,因为它实际上是滥用内部阶级机制。

只需将扩展的内部类放在同一个外部类中!

更新2:

我的代码中发生的事情,基于使用调试器的运行时检查以及检查类的javap检查的输出,InnerBaseOuterExtendsOuter$InnerExtendsInner都具有名为{{的合成私有最终字段1}}。因为没有显式定义构造函数,所以使用默认构造函数和代码片段

this$0

导致这两个字段都引用 OuterExtendsOuter outer = new OuterExtendsOuter(); Outer.InnerBase inner = outer.new InnerExtendsInner();

换句话说,Paŭlo的评论是完全正确的。

通过进一步的实验,如果你在outer的另一个内部类中扩展InnerBase,实际上会发生同样的情况,因此它与在同一个外部类或它的扩展中定义它几乎没有关系,但实际上是一般处理非静态内部类的结果。

我怀疑这是在某处记录的,但我还没有看到。

可能最好尽可能少地混合继承和内部类!

答案 4 :(得分:1)

在InnerBase中只有一个getter方法吗?

class Outer {
  int some_member;

  abstract class InnerBase {
    abstract void method();
    protected int getSome_Member() // This is possible, because Abstract classes can have non-abstract methods.
    {
       return some_member;
    }
  }
}

class OuterExtendsInner extends Outer.InnerBase {
  OuterExtendsInner(Outer o) { o.super(); }
  void method() {
       // you can access "some_member" now
      int myNumber = getSome_Member();

  }
}

答案 5 :(得分:0)

您的问题是InnerBase的每个实例(我知道它是抽象的)必须引用Outer对象。这是嵌套类语义的一部分。实例化OuterExtendsInner需要这样的参考。 您可以避免使InnerBase成为static嵌套类。

答案 6 :(得分:0)

如果将内部类编译为“.class”,则外部类可以扩展内部类。

现在,每次编译外部类时,它都会遇到“extends innerclass”,即

尚未编译,编译器将抛出NoClassDefException或ClassNotFoundException。

不是吗?所以你永远不会编译内部类。如果你能克服这个问题

然后你也可以扩展内部类:)。