Class inheritance with the main constructor

I have a parent class like this:

interface ITask { }

open class Task(val targetServer: Server) : ITask { }

      

Then there is a child element that inherits from it and overrides the primary constructor like this:

data class FileTask(val sourceServer: Server, targetServer: Server) : Task(targetServer = targetServer) {

}

      

This throws a compile error in eclipse as

The primary constructor of a data class should only have property parameters (val / var)

Removing the keyword data

from the class header will throw an error, but I don't understand why.

Keeping the keyword data

and adding var

to targetServer

gives another error

'targetServer' hides member of supertype 'Task' and needs modification 'override'

Adding override

in targetServer

for override var targetServer: Server

raises another error

"targetServer" in "Task" is final and cannot be overridden

I need help to understand these errors.

+3


source to share


2 answers


The original error is that a data class cannot have parameters in its main constructor other than properties val

or var

. Removing the keyword data

removes this restriction.

It was mentioned that data classes usually do not work well with inheritance. It is assumed that they are used as simple data transfer objects and are not suitable for participating in hierarchies because it becomes difficult to understand what properties will be considered in the generated method implementations. It's best not to use them at all.

Read more about data classes and inheritance here - this is a proposal that was implemented in Kotlin 1.1.


To get back to the specific issue, if you really should make this class a data class, you can mark the property in the base class as open

and then override it in FileTask

, like:

open class Task(open val targetServer: Server) : ITask

data class FileTask(val sourceServer: Server, override val targetServer: Server): Task(targetServer = targetServer)

      



It basically hides the property declared in Task

and always accesses the property in FileTask

.

I don't know what your exact requirements are for your classes, but one thing you could do to clean it up and make it a little better is to do Task

its abstract property too targetServer

, for example

abstract class Task : ITask {
    abstract val targetServer: Server
}

data class FileTask(val sourceServer: Server, override val targetServer: Server) : Task()

      

This way you won't have an unnecessary property (and backing field) in the base class, and you have to have a property targetServer

in all classes that inherit from Task

. You can also take it even further and put the property in an interface ITask

.

interface ITask {
    val targetServer: Server
}

      

+8


source


I know this is a very old post, but I was struggling with the same problem and doing a superclass abstraction was not a solution. You just need to do the following:

change this value

open class Task(val targetServer: Server) : ITask { }

      



to (Note that I made the targetServer variable open)

open class Task(open val targetServer: Server) : ITask { }

      

0


source







All Articles