数据类似乎是Java中老式pojo的替代品。这些类允许继承是可以预料的,但我看不出扩展数据类的方便方法。我需要的是这样的东西:

open data class Resource (var id: Long = 0, var location: String = "")
data class Book (var isbn: String) : Resource()

上面的代码失败是因为component1()方法的冲突。只在一个类中留下数据注释也不能完成这项工作。

也许还有另一种扩展数据类的习惯用法?

UPD:我可能只注释子子类,但数据注释只处理构造函数中声明的属性。也就是说,我必须声明所有的父属性是开放的,并重写它们,这是丑陋的:

open class Resource (open var id: Long = 0, open var location: String = "")
data class Book (
    override var id: Long = 0,
    override var location: String = "",
    var isbn: String
) : Resource()

当前回答

我是怎么做到的。

open class ParentClass {
  var var1 = false
  var var2: String? = null
}

data class ChildClass(
  var var3: Long
) : ParentClass()

它工作得很好。

其他回答

我想要继承的数据类没有不应该封装在接口中的行为。通过为接口的“普通”实现者提供私有数据类,所有对象都可以获得数据的好处,而UnitVector就像是对V的扩展。

interface Vector {
    companion object {
        fun build(x : Float ...) : Vector = V(x ...)
        private data class V(override val x : Float ...) : Vector
    }
    val x : Float
    //functions, y etc. 
} 
data class UnitVector(override var x : Float ...) : Vector {
    init {
        //special behavior
    } 
}

实现继承的另一种方法是使用带有抽象值的类

sealed class Parent {
    
    abstract val someVal: String
    
    data class Child1(override val someVal: String) : Parent()
    
    data class Child2(override val someVal: String) : Parent()
}

可以从非数据类继承数据类。不允许从另一个数据类继承数据类,因为在继承的情况下,无法使编译器生成的数据类方法一致且直观地工作。

上述方案使用抽象类实际生成相应的类,并让数据类从它扩展。

如果您不喜欢抽象类,那么使用接口如何?

Kotlin中的接口可以具有本文所示的属性。

interface History {
    val date: LocalDateTime
    val name: String
    val value: Int
}

data class FixedHistory(override val date: LocalDateTime,
                        override val name: String,
                        override val value: Int,
                        val fixedEvent: String) : History

我很好奇Kotlin是如何编译的。下面是等价的Java代码(使用Intellij [Kotlin字节码]特性生成):

public interface History {
   @NotNull
   LocalDateTime getDate();

   @NotNull
   String getName();

   int getValue();
}

public final class FixedHistory implements History {
   @NotNull
   private final LocalDateTime date;
   @NotNull
   private final String name;
   private int value;
   @NotNull
   private final String fixedEvent;

   // Boring getters/setters as usual..
   // copy(), toString(), equals(), hashCode(), ...
}

正如您所看到的,它的工作方式完全像一个普通的数据类!

@Željko trogrliic的答案是正确的。但是我们必须像在抽象类中一样重复相同的字段。

同样,如果我们在抽象类中有抽象子类,那么在数据类中我们不能从这些抽象子类扩展字段。我们应该首先创建数据子类,然后定义字段。

abstract class AbstractClass {
    abstract val code: Int
    abstract val url: String?
    abstract val errors: Errors?

    abstract class Errors {
        abstract val messages: List<String>?
    }
}



data class History(
    val data: String?,

    override val code: Int,
    override val url: String?,
    // Do not extend from AbstractClass.Errors here, but Kotlin allows it.
    override val errors: Errors?
) : AbstractClass() {

    // Extend a data class here, then you can use it for 'errors' field.
    data class Errors(
        override val messages: List<String>?
    ) : AbstractClass.Errors()
}