Scala子类访问父类方法局部变量及null值问题求解
问题核心原因
两个问题本质是对JVM面向对象执行逻辑、Scala类初始化规则理解偏差导致的:
- 子类打印不执行:main方法中仅创建了
Application父类实例,全程没有实例化App子类。子类构造块内的逻辑(包括你写的println("Inside of APP"))只有在创建子类实例时才会触发,不new子类就永远不会执行。你调整后的版本把new App()写在App类的构造代码内部,会触发无限递归实例化,直接抛出栈溢出错误,写法本身不成立。 mypath取值为null:给mypath赋值的逻辑写在functionname()方法内部,类初始化阶段只会执行类体中直接定义的语句,不会自动调用成员方法。此时mypath未被赋值,String类型的默认值就是null。只有手动调用过functionname()之后,mypath才会被写入对应的路径值。
修正方案
你要求“仅实例化一次”的限制完全可以满足:App是Application的子类,实例化App得到的对象本身就是合法的Application类型实例,不需要额外创建父类对象。
修正后的可运行代码如下:
class App extends Application { println("Inside of APP") println(s"子类构造阶段mypath值:$mypath") } class Application { var mypath: String = _ def functionname(): Int = { val exitCode = 0 val localPath: String = "C:/path" mypath = localPath println(s"方法内打印localPath:$localPath") exitCode } // 父类构造阶段执行 println(s"父类构造阶段mypath值:$mypath") } object HelloWorld { def main(args: Array[String]): Unit = { // 仅实例化一次,用父类类型接收子类实例,符合多态规则 val origin: Application = new App() println("===== 调用方法前 =====") println(origin.mypath) println("===== 调用方法 =====") val code = origin.functionname() println(s"方法返回值:$code") println("===== 调用方法后 =====") println(origin.mypath) } }
运行结果说明
执行上述代码的输出顺序如下:
父类构造阶段mypath值:null Inside of APP 子类构造阶段mypath值:null ===== 调用方法前 ===== null ===== 调用方法 ===== 方法内打印localPath:C:/path 方法返回值:0 ===== 调用方法后 ===== C:/path
注意:Scala类初始化顺序固定为先执行父类构造逻辑,再执行子类构造逻辑。如果你需要对象创建完成时
mypath就有值,就把路径赋值逻辑从functionname()挪到类构造块中;如果路径值本身是functionname()执行过程中才生成的,那必须等方法调用完成后才能拿到非null的路径值,不存在绕过方式。
如果坚持只实例化纯Application类、不实例化子类,子类的所有逻辑永远不会执行——父类实例不会感知到子类的存在,这是面向对象的基本规则。
内容的提问来源于stack exchange,提问作者ProSyth
相关产品推荐
相关产品推荐

