重写protected方法后为何无法访问public版本的该方法?
访问修饰符重写的误区解析
先看第一段正常运行的代码:
fun main() { val b: AAA = BBB() b.testA() } open class AAA { fun testA() { println("This is testA()") } } open class BBB : AAA()
运行结果:
This is testA()
这段代码中,b调用并输出了AAA类的testA(),没有问题。
第二段重写方法的代码:
fun main() { val b: AAA = BBB() b.testA() } open class AAA { open fun testA() { println("This is testA()") } } class BBB : AAA() { override fun testA() { println("This is overridden testA() ") } }
运行结果:
This is overridden testA()
这段代码也正常,因为testA()被重写,调用的是BBB类的实现。
现在是出现问题的代码:
fun main() { val b: AAA = BBB() b.testA() } open class AAA { protected open fun testA() { println("This is testA()") } } class BBB : AAA() { public override fun testA() { println("This is overridden testA()") } }
IDE提示错误:Cannot access 'testA': it is protected in 'AAA'
明明BBB把testA()重写为public,为什么不能像第二段代码那样调用BBB的实现?问题出在哪?
核心问题解析
你陷入的误区是混淆了编译阶段的访问权限检查和运行阶段的方法动态分派:
- 访问权限看静态类型:变量
b的静态类型是AAA,编译器在编译时只会依据AAA的定义做权限校验。AAA中的testA()是protected,意味着该方法仅能在AAA内部或其子类中访问,main()函数不属于这两个范围,因此直接编译报错,根本不会进入运行阶段。 - 方法重写影响运行逻辑:虽然
BBB将重写后的方法改为public,但这只对以BBB为静态类型的变量生效。如果把b的类型声明为BBB,或者在BBB内部调用testA(),就能正常访问。
比如修改main()代码即可正常运行:
fun main() { val b: BBB = BBB() // 静态类型改为BBB b.testA() // 正常调用BBB的public方法 }
总结:方法重写决定了运行时执行哪个实现,但访问权限是编译阶段基于静态类型的检查规则,子类放宽重写方法的权限,无法突破父类在静态类型下的访问限制。
内容的提问来源于stack exchange,提问作者ybybyb
相关产品推荐
相关产品推荐

