I have the following classes structure:
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'
}
I got an exception Kotlin: Cannot access 'm': it is protected in 'Abstr'
It little bit confusing, because the same structure is legal for java.
According to kotlin docs
- protected — visible inside this class only + visible in subclasses too;
Is it bug or expected behavior?
In Kotlin if you override a protected member and do not specify the visibility explicitly, the overriding member will also have protected visibility. In Java the visibility is according to the modifier and the default is still public .
Yes, you can declare an abstract method protected. If you do so you can access it from the classes in the same package or from its subclasses.
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
A Kotlin abstract class is similar to Java abstract class which can not be instantiated. This means we cannot create objects of an abstract class. However, we can inherit subclasses from a Kotlin abstract class.
It is designed behavior
Protected modifier in Kotlin similar to Java, but has additional restrictions.
Protected in Java:
Protected in Kotlin:
So, according to the code in question we cannot access protected method
class Child : Abstr(){
private val subChild: Abstr = Child()
override fun m() = subChild.m() //Trying to access not inherited method
}
There is similar restriction in Java, when we trying to access protected member from another package:
// 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
}
}
There is answer in issue tracker from Kotlin team: https://youtrack.jetbrains.com/issue/KT-21048
The current behavior is by design.
By calling subChild.m()
you're trying to access an instance of Abstr
from outside the object, so protected
access prevents you from doing this.
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
's fun from the child class. It will work fine.protected
variable from the child class. It will work fine.protected
fun outside the context of the child class. This will not work.protected
to internal
or public
.private val subChild = Child()
.Note: in case you will use m() from other children of ParentCl you need to enlarge the visibility scope inside child class: public override fun m() {...}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With