if (personModification.firstName != null) {person.firstName = personModification.firstName}
if (personModification.lastName != null) {person.lastName = personModification.lastName}
if (personModification.job != null) {person.job = personModification.job}
class Person (val firstName: String?,
val lastName: String?,
val job: String?)
class PersonModification(val firstName: String?,
val lastName: String?,
val job: String?)
如果PersonModification
属性不是null
,则任务是使用PersonModification
值覆盖任何Person
属性值。如果您关心,这背后的业务逻辑是一个APIendpoint,它修改person
,并将personmodifiation
作为参数(但可以更改所有或任何属性,因此我们不希望用null覆盖有效的旧值)。解决这个问题的方法是这样的。
if (personModification.firstName != null) {person.firstName = personModification.firstName}
if (personModification.lastName != null) {person.lastName = personModification.lastName}
if (personModification.job != null) {person.job = personModification.job}
我被告知这是多余的(我同意)。解决方案伪代码如下所示:
foreach(propName in personProps){
if (personModification["propName"] != null) {person["propName"] = personModification["propName"]}
}
当然,这不是JavaScript,所以没那么容易。我的反射解决方案在下面,但imo,有冗余比在这里做反射更好。我有什么其他选择来删除冗余?
package kotlin.reflect;
class Person (val firstName: String?,
val lastName: String?,
val job: String?)
class PersonModification(val firstName: String?,
val lastName: String?,
val job: String?)
// Reflection - a bad solution. Impossible without it.
//https://stackoverflow.com/questions/35525122/kotlin-data-class-how-to-read-the-value-of-property-if-i-dont-know-its-name-at
inline fun <reified T : Any> Any.getThroughReflection(propertyName: String): T? {
val getterName = "get" + propertyName.capitalize()
return try {
javaClass.getMethod(getterName).invoke(this) as? T
} catch (e: NoSuchMethodException) {
null
}
}
fun main(args: Array<String>) {
var person: Person = Person("Bob","Dylan","Artist")
val personModification: PersonModification = PersonModification("Jane","Smith","Placeholder")
val personClassPropertyNames = listOf("firstName", "lastName", "job")
for(properyName in personClassPropertyNames) {
println(properyName)
val currentValue = person.getThroughReflection<String>(properyName)
val modifiedValue = personModification.getThroughReflection<String>(properyName)
println(currentValue)
if(modifiedValue != null){
//Some packages or imports are missing for "output" and "it"
val property = outputs::class.memberProperties.find { it.name == "firstName" }
if (property is KMutableProperty<*>) {
property.setter.call(person, "123")
}
}
})
}
您可以复制并粘贴到这里来运行它:https://try.kotlinlang.org/
编写一个5行的helper来实现这一点应该非常简单,它甚至支持复制每个匹配的属性或只是属性的选择。
但是,如果您正在编写Kotlin代码并大量使用数据类和val
(不可变属性),这可能并不有用。查看一下:
fun <T : Any, R : Any> T.copyPropsFrom(fromObject: R, skipNulls: Boolean = true, 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 ->
val copyValue = matchingProp.getter.call(fromObject);
if (!skipNulls || (skipNulls && copyValue != null)) {
targetProp.setter.call(this, copyValue)
}
}
}
}
这种方法使用反射,但它使用的是非常轻量级的Kotlin反射。我还没有计时任何东西,但它应该以与手动复制属性几乎相同的速度运行。
现在给出两个类:
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=)
问题内容: 我有一个组件。 如果组件没有,我想将prop设置为,否则in可以是可选的。我怎么做? 不需要道具: 需要道具: 如果和为空,则抛出错误,说是 propTypes: 谢谢 问题答案: 您不需要其他库,“ prop- types”提供了现成的功能。参见https://facebook.github.io/react/docs/typechecking-with- proptypes.htm
问题内容: 我的老板说我应该使用,因为它比更好,但是他不记得为什么这样做。有什么理由要使用吗? 我以某种方式感觉到…相反! 在Google上进行搜索后,我发现的唯一结果是: 在C语言中,它可以防止您意外地在条件结构中键入(obj = null)。 问题答案: 您不能通过输入来意外分配给它。但是,这是C时代的回忆,在Java中是不可能的,因为表达式返回赋值的右侧。由于不是,编译器会抱怨。 我会尽力向
升级到Vue 2.0我有很常见的问题 我得到警告: 避免直接改变道具,因为每当父组件重新渲染时,该值将被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“用户名”(在组件中找到) 我读了很多次文档,但仍然不明白如何修复它。 和在主Vue应用中声明。 这是我的代码: 我尝试了,但它似乎不起作用,我不明白为什么。它应该将该值绑定到父级(主Vue应用程序)
问题内容: 在管理员中,我想在修改对象时禁用字段,但是在添加新对象时将其设为必填字段。 django如何处理这个问题? 问题答案: 你可以覆盖管理员的方法:
本文向大家介绍请编写一个对象obj满足 obj=='a' && obj=='b' && obj=='c'相关面试题,主要包含被问及请编写一个对象obj满足 obj=='a' && obj=='b' && obj=='c'时的应答技巧和注意事项,需要的朋友参考一下
The obj-model component loads a 3D model and material using a Wavefront(.OBJ) file and a .MTL file. Example We can load an .OBJ model by pointing to assets that specify the path to an .OBJ and .MTL fi