有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

具有主构造函数的java继承类

我有一个父类,如下所示

interface ITask { }

open class Task(val targetServer: Server) : ITask { }

然后有一个子级继承它并重写主构造函数,如下所示

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

}

这是在eclipse中抛出一个编译错误

Data class primary constructor must have only property (val / var) parameters

从类头中删除data关键字将消除错误,但我不明白为什么

保留data关键字并将var添加到targetServer会产生另一个错误

'targetServer' hides member of supertype 'Task' and needs 'override' modifier

override添加到targetServeroverride var targetServer: Server引发另一个错误

'targetServer' in 'Task' is final and cannot be overridden

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


共 (2) 个答案

  1. # 1 楼答案

    初始错误是因为数据类在其主构造函数中不能有valvar属性以外的参数。删除data关键字将解除此限制

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

    关于数据类和继承的更多信息,here是在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()
    

    这样,在基类中就不会有不必要的属性(和backing字段),并且在从Task继承的所有类中都必须有targetServer属性。您还可以更进一步,将属性也放在ITask接口中

    interface ITask {
        val targetServer: Server
    }
    
  2. # 2 楼答案

    我知道这是一篇非常古老的帖子,但我也在为同样的问题而挣扎,而将我的超类抽象并不是一个解决方案。 您只需执行以下操作:

    改变这个

    open class Task(val targetServer: Server) : ITask { }
    

    to(请注意,我已使targetServer变量打开)

    open class Task(open val targetServer: Server) : ITask { }