使用主构造函数继承类

Amr*_*awy 5 java kotlin

我有一个父类如下,

interface ITask { }

open class Task(val targetServer: Server) : ITask { }
Run Code Online (Sandbox Code Playgroud)

然后有一个孩子继承它并覆盖主要构造函数,如下所示,

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

}
Run Code Online (Sandbox Code Playgroud)

这在eclipse中引发了编译错误

数据类主构造函数必须只有property(val/var)参数

data从类标题中删除 关键字将导致错误,但我不明白为什么.

保留data关键字并添加vartargetServer 另一个错误

'targetServer'隐藏超类'Task'的成员,需要'override'修饰符

添加overridetargetServeroverride var targetServer: Server抛出另一个错误

"任务"中的"targetServer"是最终版,无法覆盖

我需要一些帮助才能理解这些错误.

zsm*_*b13 12

最初的错误是因为数据类的主要构造函数不能包含valvar属性.删除data关键字会解除此限制.

有人提到数据类通常不能很好地继承.它们应该被用作简单的数据传输对象,并且不适合参与层次结构,因为很难理解在生成的方法的实现中将考虑哪些属性.你最好的选择可能就是不要在这里使用它们.

欲了解更多有关数据类和继承,这里是在科特林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)
Run Code Online (Sandbox Code Playgroud)

这基本上隐藏了声明的属性Task,并始终访问该属性FileTask.

我不知道你对你的课程的确切要求是什么,但是你可以做的一件事就是清理它并使它更好一点就是使它Task和它的targetServer属性抽象,如下所示:

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

data class FileTask(val sourceServer: Server, override val targetServer: Server) : Task()
Run Code Online (Sandbox Code Playgroud)

这样,您就不会在基类中拥有不必要的属性(和支持字段),并且您将被迫targetServer在所有继承的类中拥有属性Task.您还可以更进一步,并将属性放在ITask界面中.

interface ITask {
    val targetServer: Server
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的详细说明。参数的关键字“open”是解决方案,但我想理解。另一方面,我认为DTO和POCO继承和多态是完全正常的 (2认同)