在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)
当您拥有仅继承属性的数据类时,这两种方法都会出现大量重复,因为您必须再次写下您指定的所有内容 - 这根本不会扩展,并且在某种程度上感觉不对。
这是最先进的技术还是将原来的java代码翻译成kotlin的最佳方法?
答案 0 :(得分:2)
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<String>) {
val abc = Abc()
abc.a
}
}
}
但是,您的问题专门针对“数据”类。数据类是语言的一个很好的组成部分,它为我们提供了“解构”和一些有用的自动生成的解构方法(例如componentN
)。因此,使用上面的代码(并将open
添加到类以及a
和b
的声明),这里的示例派生类的实现略有不同。
internal data class AbcB (override var a: String?, override var b: String?) : NumericValue() {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val abc = AbcB("a","b")
println("b = " + abc.component2())
val n: NumericValue = abc
println("a = " + n.a)
}
}
}
这似乎是合理的,因为,您的起始示例不是数据类,您的明显愿望是使用Kotlin数据类。它为您提供了一个理想的功能(如果您需要它),代价是更多的代码。
如果您将基数声明为sealed
,将a
和b
声明为abstract
,则派生类的代码相同。
因此,对于数据类, 重复了要在派生类中作为“数据”公开的基类的任何部分(它已经公开,只是不是“数据类”特殊成员,如下例所示)。但这类似于其他环境中的覆盖。只是想一想,现在考虑以下派生类。
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
}
}
}
您将获得基类的所有成员以及派生类的新数据成员。但是如果你想要覆盖优势,那么它会再次花费一些语法错误(对于派生数据类和常规类)。
最后一点。数据类仍然具有与继承和覆盖相关的其他奇怪 - 可能仍然需要解决。 toString
,hashCode
和equals
获得了自己的特殊实现,documentation说...
如果在数据类主体或超类中的最终实现中存在equals(),hashCode()或toString()的显式实现,则不会生成这些函数,并且使用现有实现;
...我发现这令人困惑(导致我尝试而不是依赖于文档)。还有其他SO问题涉及toString
和数据类的斗争(例如:this OP trying to create a DTO)。
所以,我认为这是最先进的,并没有那么糟糕(IMO)。是的,如果你想要数据类的功能,你可以像你一样完全翻译它。