Protected members not visible in subclasses

Hi! I have an IntList open class with a protected property named items:

open class IntList(array: IntArray, offset: Int = 0, length: Int = array.size) {
    protected var items: IntArray
    var size: Int
        protected set
    val IntList.lastIndex: Int
        get() = size - 1

    init {
        size = array.size
        items = IntArray(size)

        System.arraycopy(array, offset, items, 0, length)
    }

    constructor(vararg array: Int): this(array)
    constructor(list: IntList, offset: Int = 0, length: Int = list.size): this(list.items, offset, length)

    operator fun get(index: Int): Int {
        if (index >= size) throw IndexOutOfBoundsException("index can't be >= size: $index >= $size")
        return items[index]
    }

    fun toArray(): IntArray {
        val array = IntArray(size)
        System.arraycopy(items, 0, array, 0, size)
        return array
    }

    // more stuff
}

and I have a problem with the protected property in a MutableIntList subclass:

class MutableIntList(array: IntArray, offset: Int = 0, length: Int = array.size, ordered: Boolean = true) : IntList(array, offset, length) {
    var ordered = ordered
        private set

    constructor(vararg array: Int): this(array)
    constructor(vararg array: Int, ordered: Boolean): this(array, ordered = ordered)
    constructor(list: IntList, offset: Int = 0, length: Int = list.size): this(list.items, offset, length)

    operator fun set(index: Int, value: Int) {
        if (index >= size) throw IndexOutOfBoundsException("index can't be >= size: $index >= $size")
        items[index] = value
    }
}

In the set function, the class can access its own items without a problem, but in the last constructor (or in any method that receives an instance of an IntList) I got a “Cannot access ‘items’: it is protected in ‘IntList’”.
According to the reference the protected members declared inside a class are visible in subclasses but it seems it’s not visible in instances of the superclass inside the subclass. Which is a bit odd to me.
I don’t want to make items public and despite I can use the toArray function inside the constructor, I would like to know if there’s another way to access the property directly from the subclass and why it works like this.

The current behavior is by design. protected in Java and Kotlin works this way: you can only access a protected member on an object of your type or its subtype. See e.g. java - Why can't my subclass access a protected variable of its superclass, when it's in a different package? - Stack Overflow

The workaround is to change items’s visibility to internal or public.

1 Like

My bad. I was sure this was possible in Java because in all my APIs the subclasses were in the same package as the superclass. I thought it was because of being a subclass, not because they were in the same package (I knew protected granted package visibility but always tried to avoid using it).
I blame Java for an access level with no real encapsulation that misinformed me for many years. :laughing:

Thanks! And sorry for the dumb question!

The Java compiler actually performs some tricks with access. You may have seen warnings about synthetic accessors. That is the Java compiler generating a helper method to give you access that the jvm does not provide itself. Of course Kotlin has somewhat different rules.