[英]Inheriting class with primary constructor
I have a parent class as following, 我有一个父类如下,
interface ITask { }
open class Task(val targetServer: Server) : ITask { }
Then there a child inheriting it and overriding the primary constructor as following, 然后有一个孩子继承它并覆盖主要构造函数,如下所示,
data class FileTask(val sourceServer: Server, targetServer: Server) : Task(targetServer = targetServer) {
}
This is throwing a compilation error in eclipse as 这在eclipse中引发了编译错误
Data class primary constructor must have only property (val / var) parameters 数据类主构造函数必须只有property(val / var)参数
Removing the data
keyword from the class header will kill the error, but I don't understand why. 从类标题中删除data
关键字将导致错误,但我不明白为什么。
Keeping the data
keyword and adding var
to the targetServer
gives another error 保留data
关键字并将var
添加到targetServer
会产生另一个错误
'targetServer' hides member of supertype 'Task' and needs 'override' modifier 'targetServer'隐藏超类'Task'的成员,需要'override'修饰符
Adding override
to the targetServer
to be override var targetServer: Server
throws another error 将override
添加到targetServer
以override var targetServer: Server
会引发另一个错误
'targetServer' in 'Task' is final and cannot be overridden “任务”中的“targetServer”是最终版,无法覆盖
I need some help to understand these errors. 我需要一些帮助才能理解这些错误。
The initial error is because a data class can't have parameters in its primary constructor other than val
or var
properties. 初始错误是因为除了val
或var
属性之外,数据类的主构造函数中不能包含参数。 Removing the data
keyword lifts this restriction. 删除data
关键字会解除此限制。
It's been mentioned that data classes generally don't play well with inheritance. 有人提到数据类通常不能很好地继承。 They're supposed to be used as simple data transfer objects, and aren't really suitable for participating in hierarchies, because it becomes hard to understand which properties are going to be considered in the implementations of the generated methods. 它们应该被用作简单的数据传输对象,并且不适合参与层次结构,因为很难理解在生成的方法的实现中将考虑哪些属性。 Your best bet might be to not use them at all here. 你最好的选择可能就是不要在这里使用它们。
For more about data classes and inheritance, here is the proposal that was implemented in Kotlin 1.1. 欲了解更多有关数据类和继承, 这里是在科特林1.1实施的建议。
To get back to the specific problem, if you really have to make this class a data class, you can mark the property in the base class as open
and then override it in FileTask
, like so: 要回到特定问题,如果你真的必须使这个类成为一个数据类,你可以将基类中的属性标记为open
,然后在FileTask
覆盖它,如下所示:
open class Task(open val targetServer: Server) : ITask
data class FileTask(val sourceServer: Server, override val targetServer: Server): Task(targetServer = targetServer)
This basically hides the property declared in Task
, and always accesses the property in FileTask
instead. 这基本上隐藏了在Task
声明的属性,并且总是访问FileTask
的属性。
I don't know what your exact requirements for your classes are, but one thing you could do to clean this up and make it a bit nicer would be to make Task
and its targetServer
property abstract, like so: 我不知道你对你的类的确切要求是什么,但是你可以做的一件事就是清理它并让它更好一点就是使Task
及其targetServer
属性抽象,如下所示:
abstract class Task : ITask {
abstract val targetServer: Server
}
data class FileTask(val sourceServer: Server, override val targetServer: Server) : Task()
This way you wouldn't have the unnecessary property (and backing field) in the base class, and you'd be forced to have a targetServer
property in all the classes that inherit from Task
. 这样,您就不会在基类中拥有不必要的属性(和支持字段),并且您将被迫在从Task
继承的所有类中拥有targetServer
属性。 You could also take this a step further, and put the property in the ITask
interface as well. 您还可以更进一步,并将属性放在ITask
界面中。
interface ITask {
val targetServer: Server
}
I know this is a very old post, but I was struggling with the same issue and making my superclass abstract was not a solution. 我知道这是一个非常古老的帖子,但我正在努力解决同样的问题并且使我的超类抽象不是一个解决方案。 You just need to do the following: 您只需要执行以下操作:
change this 改变这一点
open class Task(val targetServer: Server) : ITask { }
to (Please note, I have made targetServer variable to open) to(请注意,我已经打开了targetServer变量)
open class Task(open val targetServer: Server) : ITask { }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.