Kotlin无法访问受保护的抽象方法
我有以下的类结构:
abstract class Abstr{ protected abstract fun m() } class Child : Abstr(){ private val subChild: Abstr = Child() override fun m() = subChild.m()// Error:(12, 18) Kotlin: Cannot access 'm': it is protected in 'Abstr' }
我遇到了一个exceptionKotlin: Cannot access 'm': it is protected in 'Abstr'
这有点混乱,因为相同的结构是合法的Java。
根据kotlin文档
- protected – 仅在此类中可见+在子类中也可见;
它是错误还是预期的行为?
目前的行为是由设计。
通过调用subChild.m()
你试图从对象之外访问一个subChild.m()
的实例,所以protected
访问阻止你这样做。
让我来举个简单的例子来澄清一下这个案子
abstract class ParentCl { protected var num = 1 protected open fun m(){ } } class ChildCl : ParentCl() { private val a0 : ParentCl = ChildCl() override fun m() { super.m() // 1-st case num = 2 // 2-nd case a0.m() // 3-rd case } }
- 你正在调用
protected
ParentCl
从子类中获得乐趣。 它会正常工作。 - 您正在修改子类的
protected
variables。 它会正常工作。 - 你在孩子class级的环境之外调用
protected
乐趣。 这是行不通的。
取决于你的目标是什么,有两个解决方案:
- 如果您想从ParentCl中调用m(),则需要将
protected
的可见性更改为internal
或public
。 - 如果你想从子类中调用m(),你需要声明variables而不需要父类的显式types:
private val subChild = Child()
。
注意:如果您将使用 ParentCl的其他子项中的m(),则需要放大子类中的可见性范围: public override fun m() {...}
这是设计的行为
Kotlin中受保护的修饰符类似于Java,但有其他限制。
在Java中保护 :
- 可见的吸入性
- 在包中可见
保护在Kotlin :
- 可见的吸入性
所以,根据有关的代码,我们无法访问受保护的方法
class Child : Abstr(){ private val subChild: Abstr = Child() override fun m() = subChild.m() //Trying to access not inherited method }
Java中有类似的限制,当我们试图从另一个包中访问受保护的成员时:
// FILE: a/SuperClass.java package a; public class SuperClass { protected void superFunction() {} } // FILE: b/ChildClass.java package b; public class ChildClass extends SuperClass { void testFunction() { ((SuperClass) new ChildClass()).superFunction(); // ERROR: superFunction() has protected access in a.SuperClass } }
Kotlin团队的问题跟踪器中有答案: https : //youtrack.jetbrains.com/issue/KT-21048
这可能是一个错误。
当我加入{}时,一切都变好了。
abstract class Abstr{ protected abstract fun m() } class Child : Abstr(){ private val subChild: Abstr = Child() override fun m() { subChild.m() // Compiles fine } }
在https://discuss.kotlinlang.org/上创建问题
或在Slack http://slack.kotlinlang.org/上写