Kotlin无法访问受保护的抽象方法

时间:2017-10-30 12:49:08

标签: 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'
}

我遇到了异常Kotlin: Cannot access 'm': it is protected in 'Abstr'

有点令人困惑,因为相同的结构对于java来说是合法的。

根据kotlin docs

  
      
  • protected - 仅在此类中可见+在子类中可见;
  •   

是错误还是预期的行为?

4 个答案:

答案 0 :(得分:5)

这是设计行为

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

答案 1 :(得分:3)

目前的行为是设计上的。

通过调用subChild.m(),您尝试从对象外部访问Abstr的实例,因此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
        }
    }
  1. 您正在从儿童班调用protected ParentCl的乐趣。它会正常工作。
  2. 您正在修改子类中的protected变量。它会正常工作。
  3. 您正在调用子类的上下文中的protected有趣 。这不起作用。
  4. 取决于您的目标是什么,有两种解决方案:

    1. 如果您想从ParentCl调用m(),则需要将可见性从protected更改为internalpublic
    2. 如果您想从子类调用m(),则需要声明该变量而不使用其父类的显式类型:private val subChild = Child()
    3. 注意:如果您使用来自ParentCl的其他子的m(),您需要扩大子类内的可见范围:public override fun m() {...}

答案 2 :(得分:0)

这可能是一个错误。

当我添加{}时,一切都变好了。

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/

答案 3 :(得分:0)

受保护的-与私有+相同,也可以在子类中看到;

elif isinstance(u.port, type(None)):
    print(' None')

在您的子类中

abstract class BaseActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(getLayoutResId())

} 

   protected open fun getPageTitle() = SpannableString(getString(R.string.app_name))
}

有关详细信息,请参阅文档

visibility-modifiers

Classes