复制同名属性的简单代码?

Ray*_*ond 4 java spring kotlin

我有一个问题在我脑海中存在了很长时间。当我在 Spring 中编写代码时,有很多 DTO、域对象的脏代码和无用代码。对于语言层面,我对 Java 无望,但在 Kotlin 中看到了一些曙光。这是我的问题:

样式 1 我们通常会编写以下代码(Java、C++、C#、...)

    // annot: AdminPresentation 
    val override = FieldMetadataOverride()
    override.broadleafEnumeration = annot.broadleafEnumeration
    override.hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
    override.fieldComponentRenderer = annot.fieldComponentRenderer
Run Code Online (Sandbox Code Playgroud)

Sytle 2之前的代码可以通过T.apply()在 Kotlin 中使用来简化

    override.apply {
        broadleafEnumeration = annot.broadleafEnumeration
        hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
        fieldComponentRenderer = annot.fieldComponentRenderer
    }
Run Code Online (Sandbox Code Playgroud)

Sytle 3 这样的代码甚至可以简化成这样吗?

    override.copySameNamePropertiesFrom (annot) { // provide property list here
        broadleafEnumeration
        hideEnumerationIfEmpty
        fieldComponentRenderer
    }
Run Code Online (Sandbox Code Playgroud)

第一优先要求

  1. property name只提供一次清单
  2. property name提供正常的代码,以便我们可以得到IDE自动完成功能。

第二优先要求

  1. 最好避免样式 3 的运行时成本。(例如,“反射”可能是一种可能的实现,但它确实会引入成本。)
  2. 它更喜欢直接生成像 style1/style2 这样的代码。

不关心

  1. 样式 3 的最终语法。

我是 Kotlin 语言的新手。是否可以使用 Kotlin 来定义诸如“样式 3”之类的东西?

Str*_*lok 5

编写一个 5 行帮助程序来执行此操作应该非常简单,它甚至支持复制每个匹配的属性或只是选择的属性。

尽管如果您正在编写 Kotlin 代码并大量使用数据类和val(不可变属性),它可能没有用。一探究竟:

fun <T : Any, R : Any> T.copyPropsFrom(fromObject: R, vararg props: KProperty<*>) {
  // only consider mutable properties
  val mutableProps = this::class.memberProperties.filterIsInstance<KMutableProperty<*>>()
  // if source list is provided use that otherwise use all available properties
  val sourceProps = if (props.isEmpty()) fromObject::class.memberProperties else props.toList()
  // copy all matching
  mutableProps.forEach { targetProp ->
    sourceProps.find {
      // make sure properties have same name and compatible types 
      it.name == targetProp.name && targetProp.returnType.isSupertypeOf(it.returnType) 
    }?.let { matchingProp ->
      targetProp.setter.call(this, matchingProp.getter.call(fromObject))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这种方法使用反射,但它使用非常轻量级的 Kotlin 反射。我没有对任何东西计时,但它的运行速度应该与手动复制属性的速度几乎相同。

现在给出2个类:

data class DataOne(val propA: String, val propB: String)
data class DataTwo(var propA: String = "", var propB: String = "")
Run Code Online (Sandbox Code Playgroud)

您可以执行以下操作:

  var data2 = DataTwo()
  var data1 = DataOne("a", "b")
  println("Before")
  println(data1)
  println(data2)
  // this copies all matching properties
  data2.copyPropsFrom(data1)
  println("After")
  println(data1)
  println(data2)
  data2 = DataTwo()
  data1 = DataOne("a", "b")
  println("Before")
  println(data1)
  println(data2)
  // this copies only matching properties from the provided list 
  // with complete refactoring and completion support
  data2.copyPropsFrom(data1, DataOne::propA)
  println("After")
  println(data1)
  println(data2)
Run Code Online (Sandbox Code Playgroud)

输出将是:

Before
DataOne(propA=a, propB=b)
DataTwo(propA=, propB=)
After
DataOne(propA=a, propB=b)
DataTwo(propA=a, propB=b)
Before
DataOne(propA=a, propB=b)
DataTwo(propA=, propB=)
After
DataOne(propA=a, propB=b)
DataTwo(propA=a, propB=)
Run Code Online (Sandbox Code Playgroud)