From c20af2bd30c22cbfde78732de8b005cd27d811c6 Mon Sep 17 00:00:00 2001 From: sjsdfg <736777445@qq.com> Date: Sat, 15 Jun 2019 20:13:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=B0=8F=E8=8A=82=20?= =?UTF-8?q?=E5=86=85=E9=83=A8=E7=B1=BB=E5=8F=AF=E4=BB=A5=E8=A2=AB=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E4=B9=88=EF=BC=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/11-Inner-Classes.md | 91 ++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/docs/book/11-Inner-Classes.md b/docs/book/11-Inner-Classes.md index 9b173fb..65d2c3e 100644 --- a/docs/book/11-Inner-Classes.md +++ b/docs/book/11-Inner-Classes.md @@ -1193,7 +1193,96 @@ enclosingClassReference.super(); -## 内部类可以被重写么? +## 内部类可以被覆盖么? + +如果创建了一个内部类,然后继承其外围类并重新定义此内部类时,会发生什么呢?也就是说,内部类可以被覆盖吗?这看起来似乎是个很有用的思想,但是“覆盖”内部类就好像它是外围类的一个方法,其实并不起什么作用: + +```java +// innerclasses/BigEgg.java +// An inner class cannot be overridden like a method +class Egg { + private Yolk y; + protected class Yolk { + public Yolk() { + System.out.println("Egg.Yolk()"); + } + } + Egg() { + System.out.println("New Egg()"); + y = new Yolk(); + } +} +public class BigEgg extends Egg { + public class Yolk { + public Yolk() { + System.out.println("BigEgg.Yolk()"); + } + } + public static void main(String[] args) { + new BigEgg(); + } +} +``` + +输出为: + +``` +New Egg() +Egg.Yolk() +``` + +默认的无参构造器是编译器自动生成的,这里是调用基类的默认构造器。你可能认为既然创建了BigEgg的对象,那么所使用的应该是“覆盖后”的Yolk版本,但从输出中可以看到实际情况并不是这样的。 + +这个例子说明,当继承了某个外围类的时候,内部类并没有发生什么特别神奇的变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内。当然,明确地继承某个内部类也是可以的: + +```java +// innerclasses/BigEgg2.java +// Proper inheritance of an inner class +class Egg2 { + protected class Yolk { + public Yolk() { + System.out.println("Egg2.Yolk()"); + } + public void f() { + System.out.println("Egg2.Yolk.f()"); + } + } + private Yolk y = new Yolk(); + Egg2() { System.out.println("New Egg2()"); } + public void insertYolk(Yolk yy) { y = yy; } + public void g() { y.f(); } +} +public class BigEgg2 extends Egg2 { + public class Yolk extends Egg2.Yolk { + public Yolk() { + System.out.println("BigEgg2.Yolk()"); + } + @Override + public void f() { + System.out.println("BigEgg2.Yolk.f()"); + } + } + public BigEgg2() { insertYolk(new Yolk()); } + public static void main(String[] args) { + Egg2 e2 = new BigEgg2(); + e2.g(); + } +} +``` + +输出为: + +``` +Egg2.Yolk() +New Egg2() +Egg2.Yolk() +BigEgg2.Yolk() +BigEgg2.Yolk.f() +``` + +现在BigEgg2.Yolk通过extends Egg2.Yolk明确地继承了此内部类,并且覆盖了其中的方法。 + +insertYolk()方法允许BigEgg2将它自己的Yolk对象向上转型为Egg2中的引用y。所以当g()调用y.f()时,覆盖后的新版的f()被执行。第二次调用Egg2.Yolk(),结果是BigEgg2.Yolk的构造器调用。