(Kotlin) Why do abstract class variables have to be declared as 'open' to be overridable?

229 Views Asked by At

I have worked on this problem for a while now, and even through the Kotlin documentation and other online sources I can't seem to find a clear answer to some of my questions.

I am attempting to code with best practices for an project which will have dozens of Android clients simultaneously communicating with a Firebase server. This is just a portion of the work I'm doing in defining the object classes. Since I want to use best practices, I'm intending to use inheritance.

I had many issues and scoured StackOverflow and the Documentation to finally figure out some of this weirdness with data/abstract/open classes and got the working code below. In making it work, I found out a lot of Kotlin's weirdness with inheritance. It seems quite redundant, which seems counter-intuitive.

Parent:

abstract class BaseUserClass(
    open val data1: String,
    open val data2: String,
    open var data3: String?
    )

Child (one of two):

data class DerivedUserClass(
    override val data1: String,
    override val data2: String,
    override var data3: String?,
    var data4: Int = 0
) : BaseUserClass(data1, data2, data3)

Still, despite this working, I feel I'm missing a lot of the actual understanding that I should have.

Why are abstract class variables unable to be set as abstract?

Why are they instead able to be set as open (in order for override to be possible)?

Is this method of inheritance really the best / most efficient method?

Might there be a better method in defining a set of object classes?

1

There are 1 best solutions below

1
Sam On

When you declare a property in the primary constructor of a Kotlin class, you're really doing two things:

  1. Creating a constructor parameter, and
  2. Creating a property with the same name as the constructor parameter, which is initialized with that parameter's value

You can't make these constructor properties abstract, because they're always initialized.

If you want to declare a property without initializing it, you can do so in the class body instead of in the constructor.

abstract class BaseUserClass {
    abstract val data1: String
}

The primary constructor parameters appear in parentheses () after the class name. The class body follows the primary constructor and is surrounded by braces {}. Both the constructor and the class body are optional, and can be omitted if they're empty.