如何使用数据类的简单inheritance?

在java中,

abstract class NumericValue{ private String a; private String b; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NumericValue that = (NumericValue) o; if (a != null ? !a.equals(that.a) : that.a != null) return false; return b != null ? b.equals(that.b) : that.b == null; } @Override public int hashCode() { int result = a != null ? a.hashCode() : 0; result = 31 * result + (b != null ? b.hashCode() : 0); return result; } } class Abc extends NumericValue{ public static void main(String[] args) { Abc abc = new Abc(); abc.getA(); } } 

在Kotlin,这归结为:

方法1:

 sealed class NumericValueA{ abstract var a: String abstract var b: String } data class AbcA( override var a:String, override var b:String ):NumericValueA() 

方法2:

 open class NumericValueB( open var a:String, open var b:String ) data class AbcB( override var a:String, override var b:String ):NumericValueB(a,b) 

如果数据类只是inheritance属性,那么这两种方法往往会大量复制,因为您必须再次写下您指定的所有内容 – 这不会缩放,而且会感觉不对。

这是最先进的技术还是真的是将以前的java代码翻译成kotlin的最好方法?

IntelliJ Idea将您的Java代码翻译成以下看起来合理并减少的版本。 所以,我会回答,“不,你的前提不能准确地描述Kotlin是否是最先进的”。

 internal abstract class NumericValue { var a: String? = null var b: String? = null override fun equals(o: Any?): Boolean { if (this === o) return true if (o == null || javaClass != o.javaClass) return false val that = o as NumericValue? if (if (a != null) a != that!!.a else that!!.a != null) return false return if (b != null) b == that.b else that.b == null } override fun hashCode(): Int { var result = if (a != null) a!!.hashCode() else 0 result = 31 * result + if (b != null) b!!.hashCode() else 0 return result } } internal class Abc : NumericValue() { companion object { @JvmStatic fun main(args: Array) { val abc = Abc() abc.a } } } 

但是,您的问题专门针对“数据”类。 数据类是语言的一个很好的组成部分,它给了我们“解构”和一些有用的自动生成的解构方法(比如componentN )。 所以,使用上面的代码(并添加open的类和ab的声明),这里是你的示例派生类的稍微不同的实现。

 internal data class AbcB (override var a: String?, override var b: String?) : NumericValue() { companion object { @JvmStatic fun main(args: Array) { val abc = AbcB("a","b") println("b = " + abc.component2()) val n: NumericValue = abc println("a = " + na) } } } 

这似乎是合理的,因为你的开始的例子不是数据类,你明显的愿望是利用Kotlin数据类。 它给你一个理想的function(如果你需要的话),代价是更多的代码。

派生类是相同的代码,如果你宣布基地sealedababstract

因此,在数据类的情况下,基类的任何部分都要在派生类中作为“数据”公开(它已经被公开,而不是“数据类”特殊成员,如图所示下面的例子)。 但这与其他情况下的替代相似。 为了思考,现在考虑下面的派生类。

 internal data class AbcCD (var c: String?, var d: String?) : NumericValue() { companion object { @JvmStatic fun x() { val abc = AbcCD("c","d") abc.b = "B" abc.a = "A" println("d = " + abc.component2()) abc.a } } } 

您将获得基类的所有成员以及派生类的新数据成员。 但是,如果你想覆盖好处,它再次花费一些语法verbage(对于派生数据类和常规类)。

最后一点。 数据类仍然有其他与遗传和覆盖相关的怪异可能仍然需要解决。 toStringhashCodeequals获取自己的特殊实现, 文档说…

如果在数据类体中存在equals(),hashCode()或toString()的显式实现或超类的最终实现,则不会生成这些函数,而是使用现有的实现;

…我发现这是令人困惑的阅读(导致我试验,而不是依靠文档)。 还有其他的SO问题涉及toString和数据类的斗争(例如: 这个OP试图创建一个DTO )。

所以 ,我认为这是最先进的,并不是那么糟糕(国际海事组织)。 是的,如果你想要数据类的function,你可以像你所做的那样翻译它。