Kotlin 数据 classes with Java super class
Kotlin data classes with Java super class
我有一个 Java class,其中包含关于数据库实体的一般信息(即它们的 ID)。
@Data
public class DbEntity {
protected final String id;
public DbEntity(String id) {
this.id = id;
}
}
我们使用 Lombok @Data
生成 getters, toString
, equals
...
在 Java 中,我将简单地扩展此 class 并再次添加 @Data
。
@Data
class JavaSubClass extends DbEntity {
public JavaSubClass(String id) {
super(id);
}
}
在较新的服务中,我们使用 Kotlin,但希望重用标准 classes,例如 DbEntity
。
我的第一种方法是简单地声明一个数据 class 例如
data class SubClass1(val id: String, val name: String) : DbEntity(id)
Accidental override: The following declarations have the same JVM signature (getId()Ljava/lang/String;):
fun <get-id>(): String defined in com.demo.SubClass1
fun getId(): String! defined in com.demo.SubClass1
经过一番阅读后,我找到了几个解决方案,但我都不是很满意。
- 不要使用数据 classes。这行得通,但留给我的任务是实施
equals
等
class SubClass4(id: String, val name: String) : DbEntity(id)
- 复制字段。这可行,但我们最终得到两个可能不同步的字段。
data class SubClass3(val subId: String, val name: String) : DbEntity(subId)
- 为 getter 指定一个不同的名称。这从根本上也复制了该字段,但隐藏了 getter.
data class SubClass2(@get:JvmName("getId_") val id: String, val name: String) : DbEntity(id)
正如我所说,我对上面提出的任何解决方案都不满意。有一个抽象的 super class 或一个接口肯定会更合适。但是,实体 class 驻留在主要 Java 项目所依赖的库中。由于新的 Kotlin 依赖项,我犹豫要不要更改它。
有没有人遇到过类似的问题并且有解决方法的建议?
作为解决方法,在 KT-6653 - Kotlin properties do not override Java-style getters and setters 修复之前,我会采用您的第 3 点的变体,即:
data class SubClass(@get:JvmName("bogusId") private val id: String, val name: String) : DbEntity(id)
此变体的好处是,您始终可以访问 "original" getId
功能。您不会使用 bogusId()
-函数,因为它不是 visible/accessible(通过反射访问它没有任何意义……您只对实际的 id
-字段感兴趣)。这对双方都有效并且看起来相似:来自 Java 以及来自 Kotlin。尽管如此,在幕后这个变体使用了 2 个字段,但在最好的情况下,您可以在将来用类似的东西替换它:
data class SubClass(override val id: String, val name : String) : DbEntity(id)
我有一个 Java class,其中包含关于数据库实体的一般信息(即它们的 ID)。
@Data
public class DbEntity {
protected final String id;
public DbEntity(String id) {
this.id = id;
}
}
我们使用 Lombok @Data
生成 getters, toString
, equals
...
在 Java 中,我将简单地扩展此 class 并再次添加 @Data
。
@Data
class JavaSubClass extends DbEntity {
public JavaSubClass(String id) {
super(id);
}
}
在较新的服务中,我们使用 Kotlin,但希望重用标准 classes,例如 DbEntity
。
我的第一种方法是简单地声明一个数据 class 例如
data class SubClass1(val id: String, val name: String) : DbEntity(id)
Accidental override: The following declarations have the same JVM signature (getId()Ljava/lang/String;):
fun <get-id>(): String defined in com.demo.SubClass1
fun getId(): String! defined in com.demo.SubClass1
经过一番阅读后,我找到了几个解决方案,但我都不是很满意。
- 不要使用数据 classes。这行得通,但留给我的任务是实施
equals
等
class SubClass4(id: String, val name: String) : DbEntity(id)
- 复制字段。这可行,但我们最终得到两个可能不同步的字段。
data class SubClass3(val subId: String, val name: String) : DbEntity(subId)
- 为 getter 指定一个不同的名称。这从根本上也复制了该字段,但隐藏了 getter.
data class SubClass2(@get:JvmName("getId_") val id: String, val name: String) : DbEntity(id)
正如我所说,我对上面提出的任何解决方案都不满意。有一个抽象的 super class 或一个接口肯定会更合适。但是,实体 class 驻留在主要 Java 项目所依赖的库中。由于新的 Kotlin 依赖项,我犹豫要不要更改它。
有没有人遇到过类似的问题并且有解决方法的建议?
作为解决方法,在 KT-6653 - Kotlin properties do not override Java-style getters and setters 修复之前,我会采用您的第 3 点的变体,即:
data class SubClass(@get:JvmName("bogusId") private val id: String, val name: String) : DbEntity(id)
此变体的好处是,您始终可以访问 "original" getId
功能。您不会使用 bogusId()
-函数,因为它不是 visible/accessible(通过反射访问它没有任何意义……您只对实际的 id
-字段感兴趣)。这对双方都有效并且看起来相似:来自 Java 以及来自 Kotlin。尽管如此,在幕后这个变体使用了 2 个字段,但在最好的情况下,您可以在将来用类似的东西替换它:
data class SubClass(override val id: String, val name : String) : DbEntity(id)