用主构造函数继承类

我有一个如下的父类,

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”是最终的,不能被覆盖

我需要一些帮助来理解这些错误。

最初的错误是因为数据类不能在valvar属性以外的主构造函数中有参数。 删除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 }