简体   繁体   English

使用主构造函数继承类

[英]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添加到targetServeroverride 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. 初始错误是因为除了valvar属性之外,数据类的主构造函数中不能包含参数。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM