首先我们要搞清楚关于closure这个单词的逻辑关系。如果说内部类是一个closure,那么外部类就是enclosing class,because OuterClass encloses InnerClass。
如果一个一般类来继承内部类,需要在构造器中使用特殊的语法。
class Outer
{
class Inner {}
}
public class ExtInner extends Outer.Inner
{
public ExtInner(Outer o)
{
o.super();
}
}
ExtInner的构造器必须要有一个Outer参数,然后调用.super();。这里要求必须使用一个enclosingClassReference.super();。
你可能会问:在ExtInner的构造器里return o.new Inner();行不行?编译器会告诉你:constructor返回的还是void。这个是本话题的意外收获。
然后ExtInner中无法通过Outer.this来连接到外部类对象,在ExtInner中使用Outer.this会得到编译错误“Outer不是封闭类”(Java SE 1.5.0_15),这里的封闭类应该就是enclosing class的意思,“Outer不是封闭类”表示Outer并没有enclose ExtInner,虽然Outer有enclose Inner,且ExtInner继承自Inner。
如果Base有一个Inner,然后Ext继承了Base,这时Ext并没有继承Base.Inner的代码,即Base.Inner的代码没有复制到Ext中。此时,如果在Ext中也写一个Inner,其实是不会发生冲突的。
如果内部类、外部类双重继承,情况如何呢?看下面代码:
class BaseOuter
{
void print()
{
System.out.println("BaseOuter prints");
}
class BaseInner
{
void print2()
{
System.out.println("BaseInner prints");
}
void print3()
{
BaseOuter.this.print();
}
}
}
class ExtOuter extends BaseOuter
{
void print4()
{
System.out.println("ExtOuter prints");
}
class ExtInner extends BaseOuter.BaseInner
{
void print5()
{
System.out.println("ExtInner prints");
}
void print6()
{
ExtOuter.this.print4();
}
void print7()
{
BaseOuter.this.print(); //error: BaseOut is not the enclosing class
}
}
}
public class ExtInnerTest
{
public static void main(String[] args)
{
ExtOuter eo = new ExtOuter();
ExtOuter.ExtInner ei = eo.new ExtInner();
ei.print2();
ei.print3();
ei.print5();
ei.print6();
ei.print7(); //error: BaseOut is not the enclosing class
}
}
可以看到ExtInner可以通过向上转型变成BaseInner,然后再连接到BaseOut.this("ei.print3();"通过编译并运行),但是不能直接使用BaseOut.this("ei.print7();" won't compile)。
总结一点,内部类不能被外部类的导出类继承,外部类也不enclose内部类的导出类。
分享到:
相关推荐
题目中的 `internal class MyClass : Base {}` 不合法,因为 `Base` 类是公开的 (`public`),而 `MyClass` 类的访问级别是内部的 (`internal`)。因此,此继承关系是 **不合法** 的。 #### 16. 断点位置 根据题目...
通过对电路设计、程序编写以及仿真测试的详细介绍,不仅展示了具体的实现方法,还加深了对5152单片机和AT24C02 EEPROM的理解。希望读者能够通过学习本项目的实施过程,掌握单片机与外部存储器通信的基本技巧,并能够...
作用域链保证了当前执行上下文对变量和函数的有序访问,它是执行上下文中的一个内部属性。 #### this 对象的理解 `this` 在JavaScript中是一个关键字,指向函数执行时的当前对象。 #### eval 函数 `eval` 函数用于...
此外,如果在一个函数内部频繁地使用未初始化的`ECX`寄存器,这可能表明该函数是某个类的成员。 **示例代码:** ```assembly mov ecx, [ebp+8] ; 假设ebp+8指向当前对象 call some_function ; 调用成员函数 ``` **...
- **定义**: 被授予对另一个类私有成员的访问权限的函数。 - **规则**: 尽量减少使用朋友函数,以保持封装性。 ##### 6.6 异常 - **原则**: 异常用于处理非常规情况,不应被滥用。 - **建议**: 使用`std::...
选项D创建了一个静态内部类,虽然不能直接访问`d1`,但可以通过对外部类的引用间接访问,所以也是正确的。因此,C和D是有效的内部类声明。 总结来说,这些面试题涵盖了Java中的基础概念,包括字符串处理、数组排序...
- 在Java中,如果没有显式指定父类,则默认继承自`Object`类。这为所有的类提供了一些基本的方法和行为。 #### 13. 项目构建问题 - 当项目文件中出现红色叹号时,通常意味着项目存在问题,如缺少必要的库文件(jar包...
内部类 - B. 适配器 - C. 接口 - D. 同步 **解析**:Java不支持传统的多重继承,但可以通过实现多个接口来模拟多重继承的效果。 #### 二十二、基本数据类型 **题目**:char类型的取值范围是多少? - A. 2^-7 ~ 2...
类的嵌套是指在一个类内部定义另一个类。这种结构可以帮助组织相关的类型,并隐藏实现细节。 #### 初始化 在C#中,可以通过构造函数来初始化类的实例。构造函数是一种特殊的方法,用于设置对象的初始状态。 #### ...
根据提供的文档信息,这里将对其中涉及的关键知识点进行详细的解析与总结。 ### 1. 标识符规则 - **题目解析**:本题考察Java中合法标识符的定义。 - **答案解析**: - **选项A** `123` 不是一个合法的标识符,...
示例代码public class ScriptTest extends TsFrame { //Fa和Fb 的fcallback参数 传递一个实现Fcallback接口的内部类 作为回调。(复杂逻辑的脚本应该使用它) @Override protected List<Fa> getFa() { List<Fa> fa= ...
可以看到,变量bart指向的就是一个Student的实例,后面的0x10a67a590是内存地址,每个对象的地址都不一样,而Student本身则是一个类。 可以自由地给一个实例变量绑定属性,例如,给实例bart绑定一个name属性: ...
`Teacher`类继承自`Person`类,并新增了一个公共成员变量`int b`。基于这些信息,我们可以分析: - 选项(a)中的`m`未定义,所以该语句无效。 - 选项(b)中的`b`是`Teacher`类的成员变量,可以直接通过`Teacher`实例`t...
- **map**: 对序列中的每一个元素应用函数。 - **reduce**: 从左至右累积地将函数应用于序列中的元素。 #### 34. 一行代码实现 9*9 乘法表 ```python print('\n'.join([' '.join([f'{i*j:2}' for j in range(1, 10...
- **定义**:继承是一种使一个类(子类)继承另一个类(父类)的特性和行为的机制。 - **优点**:提高代码复用性,便于实现多态。 - **弊端**:增加类间的耦合度,维护成本较高。 - **限制**:Java不支持多继承,但...
以上是文档中提到的一些关键知识点,Java 语言的学习涵盖了许多其他主题,包括类、对象、继承、接口、异常处理、集合框架、多线程、输入输出流等。深入理解这些概念是成为一名熟练的 Java 开发者的基础。
- **整型常量**:Java中支持多种整型常量的表示方法,包括十进制、八进制(以0开头)、十六进制(以0x或0X开头)。选项A中`078`以0开头但数值超过了八进制的最大值(7),因此不是一个有效的整型常量。 - **Set集合*...