数据类似乎是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()
Kotlin Traits可以提供帮助。
interface IBase {
val prop:String
}
interface IDerived : IBase {
val derived_prop:String
}
数据类
data class Base(override val prop:String) : IBase
data class Derived(override val derived_prop:String,
private val base:IBase) : IDerived, IBase by base
示例使用
val b = Base("base")
val d = Derived("derived", b)
print(d.prop) //prints "base", accessing base class property
print(d.derived_prop) //prints "derived"
这种方法也可以用来解决@Parcelize的继承问题
@Parcelize
data class Base(override val prop:Any) : IBase, Parcelable
@Parcelize // works fine
data class Derived(override val derived_prop:Any,
private val base:IBase) : IBase by base, IDerived, Parcelable
虽然在层次结构中正确地实现equals()确实相当困难,但支持继承其他方法仍然很好,例如:toString()。
为了更具体一点,让我们假设我们有以下结构(显然,它不起作用,因为toString()不是继承的,但如果它不是很好吗?):
abstract class ResourceId(open val basePath: BasePath, open val id: Id) {
// non of the subtypes inherit this... unfortunately...
override fun toString(): String = "/${basePath.value}/${id.value}"
}
data class UserResourceId(override val id: UserId) : ResourceId(UserBasePath, id)
data class LocationResourceId(override val id: LocationId) : ResourceId(LocationBasePath, id)
Assuming our User and Location entities return their appropriate resource IDs (UserResourceId and LocationResourceId respectively), calling toString() on any ResourceId could result in quite a nice little representation that is generally valid for all subtypes: /users/4587, /locations/23, etc. Unfortunately, because non of the subtypes inherited to overridden toString() method from the abstract base ResourceId, calling toString() actually results in a less pretty representation: <UserResourceId(id=UserId(value=4587))>, <LocationResourceId(id=LocationId(value=23))>
还有其他方法可以对上述模型进行建模,但这些方法要么迫使我们使用非数据类(错过了数据类的许多好处),要么我们最终在所有数据类中复制/重复toString()实现(没有继承)。
data class User(val id: Long, var name: String)
fun main() {
val user1 = User(id:1, name:"Kart")
val name = user1.name
println(name)
user1.name = "Michel"
val user2 = User(id:1, name:"Michel")
println(user1 == user2)
println(user1)
val updateUser = user1.copy(name = "DK DK")
println(updateUser)
println(updateUser.component1())
println(updateUser.component2())
val (id, name) = updateUser
println("$id,$name")
}
//here is the output below
检查图像为什么它显示错误id:1(编译器说使用=而不是双点,我插入的值)
可以从非数据类继承数据类。
基类
open class BaseEntity (
@ColumnInfo(name = "name") var name: String? = null,
@ColumnInfo(name = "description") var description: String? = null,
// ...
)
子类
@Entity(tableName = "items", indices = [Index(value = ["item_id"])])
data class CustomEntity(
@PrimaryKey
@ColumnInfo(name = "id") var id: Long? = null,
@ColumnInfo(name = "item_id") var itemId: Long = 0,
@ColumnInfo(name = "item_color") var color: Int? = null
) : BaseEntity()
它工作。