复制相同名称属性的简单代码? [英] Simple Code to Copy Same Name Properties?
问题描述
我有一个很久没解决的老问题.当我在Spring中编写代码时,有很多肮脏且无用的DTO域对象代码.对于语言水平,我对Java绝望了,对Kotlin也有所了解.这是我的问题:
I have an old question sustained in my mind for a long time. When I was writing code in Spring, there are lots dirty and useless code for DTO, domain objects. For language level, I am hopeless in Java and see some light in Kotlin. Here is my question:
样式1 通常,我们编写以下代码(Java,C ++,C#,...)
Style 1 It is common for us to write following code (Java, C++, C#, ...)
// annot: AdminPresentation
val override = FieldMetadataOverride()
override.broadleafEnumeration = annot.broadleafEnumeration
override.hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
override.fieldComponentRenderer = annot.fieldComponentRenderer
Sytle 2 ,可以通过在Kotlin中使用T.apply()
简化先前的代码
Sytle 2 Previous code can be simplified by using T.apply()
in Kotlin
override.apply {
broadleafEnumeration = annot.broadleafEnumeration
hideEnumerationIfEmpty = annot.hideEnumerationIfEmpty
fieldComponentRenderer = annot.fieldComponentRenderer
}
Sytle 3 这样的代码还能简化成这样的东西吗?
Sytle 3 Can such code be even simplified to something like this?
override.copySameNamePropertiesFrom (annot) { // provide property list here
broadleafEnumeration
hideEnumerationIfEmpty
fieldComponentRenderer
}
第一优先级要求
First Priority Requirments
- 仅提供一次
property name
列表 -
property name
作为常规代码提供,以便我们获得IDE自动完成功能.
- Provide
property name
list only one time - The
property name
is provided as normal code, so as to we can get IDE auto complete feature.
第二优先级要求
Second Priority Requirements
- 最好避免使用样式3的运行时成本.(例如,反射"可能是一种可能的实现,但确实会引入成本.)
- 更喜欢直接生成诸如style1/style2之类的代码.
不在乎
Not care
- 样式3的最终语法.
我是Kotlin语言的新手.是否可以使用Kotlin定义样式3"之类的内容?
I am a novice for Kotlin language. Is it possible to use Kotlin to define somthing like 'Style 3' ?
推荐答案
编写一个5行的助手来做到这一点应该很简单,它甚至支持复制每个匹配的属性或仅复制某些属性.
It should be pretty simple to write a 5 line helper to do this which even supports copying every matching property or just a selection of properties.
尽管如果您正在编写Kotlin代码并大量利用数据类和val
(不可变属性),它可能没有用.检查一下:
Although it's probably not useful if you're writing Kotlin code and heavily utilising data classes and val
(immutable properties). Check it out:
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))
}
}
}
此方法使用反射,但是使用非常轻巧的Kotlin反射.我还没有计时,但是它应该以与手动复制属性几乎相同的速度运行.
This approach uses reflection, but it uses Kotlin reflection which is very lightweight. I haven't timed anything, but it should run almost at same speed as copying properties by hand.
现在提供2个课程:
data class DataOne(val propA: String, val propB: String)
data class DataTwo(var propA: String = "", var propB: String = "")
您可以执行以下操作:
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)
输出将是:
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=)
这篇关于复制相同名称属性的简单代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!