从 java class 调用时,Kotlin 数据 class 复制功能不起作用
Kotlin data class copy function not working when called from java class
也许我误解了 data
class 的 copy
函数是如何工作的,或者可能存在错误,但以下是 copy
的示例功能未按预期工作:
科特林:
data class A {
public var x: String? = null
public var y: String? = null
public var z: B = B.ONE
}
enum class B {
ONE
TWO
THREE
}
Java
A a1 = new A()
a1.setX("Hello")
a1.setY("World")
a1.setZ(B.TWO)
A a2 = a1.copy()
// a2.x is null
// a2.y is null
// a2.z is B.ONE
似乎 copy
只是在创建 A
的新实例,而不是复制值。如果我将变量放在构造函数中,则会分配值,但这与构造新实例没有什么不同。
好吧,我在文档中漏掉了这句话:
If any of these functions is explicitly defined in the class body or inherited from the base types, it will not be generated.
事实上,这使得 copy
并不比 Java 互操作的构造函数更好。
要绕过 Kotlin 的 copy() 的限制,您可以做的是在数据中创建自己的复制函数 class。示例如下:
data class User(val name : String, val property: String) {
fun copy() : User {
//uses the fields name and property defined in the constructor
return User(name,property)
}
//or if you need a copy with a changed field
fun copy(changedProperty : String) : User {
return User(name, changedProperty)
}
}
对于与 java 的互操作,您可以制作使用 kotlin 生成的函数 .copy
@Entity
data class User(@PrimaryKey var id: Int = 0,
var firstName: String? = null,
var lastName: String? = null,
var phone: String? = null,
var email: String? = null,
var phoneCode: String? = null,
var tokenId: String? = null,
var provider: SocialProvider? = null) : Serializable {
var countryCodeIso: String? = null
set(countryCodeIso) {
if (countryCodeIso != null) {
field = countryCodeIso.toLowerCase()
}
}
fun javaCopy(): User {
val user = copy()
user.countryCodeIso = countryCodeIso
return user
}}
这个问题的搜索排名很高,可能会让 kotlin 新手感到困惑,因为该问题的示例代码不是典型的 kotlin 代码或复制功能的用法。我在下面添加了一些示例代码以帮助阐明发生了什么,并且还显示了数据 class.
的典型用法
简而言之,copy
函数在从 kotlin class 调用时最有用。我同意从 java 代码调用时它的行为并不明显。
//
// A.kt
//
// this is an idiomatic kotlin data class. note the parens around the properties, not braces.
data class A(
val x: String? = null,
val y: String? = null,
val z: B = B.ONE
) {
// this javaCopy function is completely unnecessary when being called from kotlin; it's only here to show a fairly simple way to make kotlin-java interop a little easier (like what Nokuap showed).
fun javaCopy(): A {
return this.copy()
}
}
enum class B {
ONE,
TWO,
THREE
}
fun main() {
val a1 = A("Hello", "World", B.TWO)
// here's what copy usage looks like for idiomatic kotlin code.
val a2 = a1.copy()
assert(a2.x == "Hello")
assert(a2.y == "World")
assert(a2.z == B.TWO)
// more typical is to `copy` the object and modify one or more properties during the copy. e.g.:
val a3 = a1.copy(y = "Friend")
assert(a2.x == "Hello")
assert(a3.y == "Friend")
}
public class App {
public static void main(String[] args) {
A a1 = new A("Hello", "World", B.TWO);
// the kotlin copy function is primarily meant for kotlin <-> kotlin interop
// copy works when called from java, but it requires all the args.
// calling the `javaCopy` function gives the expected behavior.
A a2 = a1.javaCopy();
assert a2.getX().equals("Hello");
assert a2.getY().equals("World");
assert a2.getZ().equals(B.TWO);
}
}
关于数据的官方文档 classes,包括 copy
函数:
https://kotlinlang.org/docs/reference/data-classes.html
也许我误解了 data
class 的 copy
函数是如何工作的,或者可能存在错误,但以下是 copy
的示例功能未按预期工作:
科特林:
data class A {
public var x: String? = null
public var y: String? = null
public var z: B = B.ONE
}
enum class B {
ONE
TWO
THREE
}
Java
A a1 = new A()
a1.setX("Hello")
a1.setY("World")
a1.setZ(B.TWO)
A a2 = a1.copy()
// a2.x is null
// a2.y is null
// a2.z is B.ONE
似乎 copy
只是在创建 A
的新实例,而不是复制值。如果我将变量放在构造函数中,则会分配值,但这与构造新实例没有什么不同。
好吧,我在文档中漏掉了这句话:
If any of these functions is explicitly defined in the class body or inherited from the base types, it will not be generated.
事实上,这使得 copy
并不比 Java 互操作的构造函数更好。
要绕过 Kotlin 的 copy() 的限制,您可以做的是在数据中创建自己的复制函数 class。示例如下:
data class User(val name : String, val property: String) {
fun copy() : User {
//uses the fields name and property defined in the constructor
return User(name,property)
}
//or if you need a copy with a changed field
fun copy(changedProperty : String) : User {
return User(name, changedProperty)
}
}
对于与 java 的互操作,您可以制作使用 kotlin 生成的函数 .copy
@Entity
data class User(@PrimaryKey var id: Int = 0,
var firstName: String? = null,
var lastName: String? = null,
var phone: String? = null,
var email: String? = null,
var phoneCode: String? = null,
var tokenId: String? = null,
var provider: SocialProvider? = null) : Serializable {
var countryCodeIso: String? = null
set(countryCodeIso) {
if (countryCodeIso != null) {
field = countryCodeIso.toLowerCase()
}
}
fun javaCopy(): User {
val user = copy()
user.countryCodeIso = countryCodeIso
return user
}}
这个问题的搜索排名很高,可能会让 kotlin 新手感到困惑,因为该问题的示例代码不是典型的 kotlin 代码或复制功能的用法。我在下面添加了一些示例代码以帮助阐明发生了什么,并且还显示了数据 class.
的典型用法
简而言之,copy
函数在从 kotlin class 调用时最有用。我同意从 java 代码调用时它的行为并不明显。
//
// A.kt
//
// this is an idiomatic kotlin data class. note the parens around the properties, not braces.
data class A(
val x: String? = null,
val y: String? = null,
val z: B = B.ONE
) {
// this javaCopy function is completely unnecessary when being called from kotlin; it's only here to show a fairly simple way to make kotlin-java interop a little easier (like what Nokuap showed).
fun javaCopy(): A {
return this.copy()
}
}
enum class B {
ONE,
TWO,
THREE
}
fun main() {
val a1 = A("Hello", "World", B.TWO)
// here's what copy usage looks like for idiomatic kotlin code.
val a2 = a1.copy()
assert(a2.x == "Hello")
assert(a2.y == "World")
assert(a2.z == B.TWO)
// more typical is to `copy` the object and modify one or more properties during the copy. e.g.:
val a3 = a1.copy(y = "Friend")
assert(a2.x == "Hello")
assert(a3.y == "Friend")
}
public class App {
public static void main(String[] args) {
A a1 = new A("Hello", "World", B.TWO);
// the kotlin copy function is primarily meant for kotlin <-> kotlin interop
// copy works when called from java, but it requires all the args.
// calling the `javaCopy` function gives the expected behavior.
A a2 = a1.javaCopy();
assert a2.getX().equals("Hello");
assert a2.getY().equals("World");
assert a2.getZ().equals(B.TWO);
}
}
关于数据的官方文档 classes,包括 copy
函数:
https://kotlinlang.org/docs/reference/data-classes.html