【问题标题】:Kotlin data class copy function not working when called from java class从 java 类调用时,Kotlin 数据类复制功能不起作用
【发布时间】:2015-02-20 02:36:54
【问题描述】:

也许我误解了data 类的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 的新实例,而不是复制值。如果我将变量放在构造函数中,则赋值,但这与构造一个新实例没有什么不同。

【问题讨论】:

    标签: java kotlin data-class


    【解决方案1】:

    好的,我错过了文档中的这句话:

    如果这些函数中的任何一个在类主体中显式定义或从基类型继承,则不会生成。

    事实上,这使得 copy 并不比 Java 互操作的构造函数更好。

    【讨论】:

    • 看起来你的例子没有呈现完整的画面:在你呈现的代码中,copy() 的无参数版本根本不适用于 Java,关于定义 copy() 的短语明确地似乎不相关。无论如何,copy() 的设计是基于默认参数机制,只有 Kotln 才有,Java 没有
    • copy() 函数在上面的例子中确实存在于 Java 中,它只是不复制任何值,因为该类没有参数。我没有提到明确定义复制功能。我只是没有完全阅读数据类的文档并误解了它们的工作原理。
    • 哦,对不起:没有复制你的例子的代码,误读了圆括号的花括号。我的坏
    【解决方案2】:

    要绕过 Kotlin 的 copy() 的限制,您可以做的是在数据类中创建自己的复制函数。下面的例子:

    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)
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      对于与 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
      }}
      

      【讨论】:

        【解决方案4】:

        这个问题的搜索排名很高,并且可能会让那些刚接触 kotlin 的人感到困惑,因为问题的示例代码不是典型的 kotlin 代码或复制功能的使用。我在下面添加了一些示例代码,以帮助阐明发生了什么,并展示了数据类的典型用法。
        简而言之,copy 函数在从 kotlin 类调用时最有用。我同意从 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);
            }
        }
        
        

        关于数据类的官方文档,包括copy 函数:
        https://kotlinlang.org/docs/reference/data-classes.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-16
          • 2020-08-17
          • 1970-01-01
          • 2021-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多