用主构造函数继承类
我有一个如下的父类,
interface ITask { } open class Task(val targetServer: Server) : ITask { }
然后有一个孩子继承它,并覆盖主要构造函数如下,
data class FileTask(val sourceServer: Server, targetServer: Server) : Task(targetServer = targetServer) { }
这是在eclipse中抛出一个编译错误
数据类主构造函数必须只有属性(val / var)参数
从类头中删除data
关键字将杀死错误,但我不明白为什么。
保持data
关键字并将var
添加到targetServer
会导致另一个错误
'targetServer'隐藏超类型'Task'的成员并需要'override'修饰符
将override
添加到要override var targetServer: Server
引发另一个错误
“任务”中的“targetServer”是最终的,不能被覆盖
我需要一些帮助来理解这些错误。
最初的错误是因为数据类不能在val
或var
属性以外的主构造函数中有参数。 删除data
关键字解除了这个限制。
有人提到数据类通常不能很好地继承。 它们应该被用作简单的数据传输对象,并不适合参与层次结构,因为在生成的方法的实现中很难理解哪些属性将被考虑。 你最好的选择可能是在这里不要使用它们。
有关数据类和继承的更多信息,请参阅Kotlin 1.1中的提议。
为了回到特定的问题,如果你真的必须把这个类作为一个数据类,你可以把基类中的属性标记为open
,然后在FileTask
覆盖它,如下所示:
open class Task(open val targetServer: Server) : ITask data class FileTask(val sourceServer: Server, override val targetServer: Server): Task(targetServer = targetServer)
这基本上隐藏了在Task
声明的属性,而总是访问FileTask
的属性。
我不知道你的类对你的确切需求是什么,但是你可以做的一件事是清理它并使其更好一点,就是让Task
和它的targetServer
属性抽象化,如下所示:
abstract class Task : ITask { abstract val targetServer: Server } data class FileTask(val sourceServer: Server, override val targetServer: Server) : Task()
这样你就不会在基类中拥有不必要的属性(和后台字段),并且你将被迫在从Task
继承的所有类中拥有一个targetServer
属性。 你也可以更进一步,把这个属性放在ITask
接口中。
interface ITask { val targetServer: Server }