在 Kotlin 中实现动态 属性 赋值
Implement Dynamic Property Assignment in Kotlin
data class Person private constructor(
var name: ObservableField<String> = ObservableField("Tony Starks"),
var age: ObservableField<Int> = ObservableField(40),
var gender: ObservableField<String> = ObservableField("Male"),
var test: String = "Tony Starks",
) {
operator fun set(key: String, value: String) {
// Tried this approach but it didn't work.
this[key] = value
}
}
我要实现的是这个;
val person = Person()
person['test'] = "James Bond"
我已经能够用 PHP
实现同样的事情
class Person {
private $name;
private $age;
private $gender;
public __get($key) {
return $this[$key];
}
public __set($key, $value) {
$this[$key] = $value;
}
}
可以在 Kotlin 中实现吗?
这种行为在像 Kotlin 这样的强类型语言中是一种反模式。通常明智的做法是不要试图强制强类型语言表现得像弱类型语言。使用强类型语言时,您的整个思维和设计方式应该有所不同。
就是说,可以通过将 class 设为 MutableMap 并将 delegating the relevant properties 设为自身来获得类似的语法。您可以通过委托(如下所示)或通过 subclassing HashMap 使其成为 MutableMap。但是,如果您使用 属性 代表,则不能将其设为 data class
。
class Person: MutableMap<String, Any?> by mutableMapOf() {
var test: String by this
init {
test = "Tony Stark"
}
override fun toString() = "Person(test='$test')"
}
fun main() {
val person = Person()
println(person)
person["test"] = "Pepper Potts"
println(person)
person.test = "Happy Hogan"
println(person["test"])
}
/** Prints:
Person(test='Tony Stark')
Person(test='Pepper Potts')
Happy Hogan
*/
这样做的缺点(类似于弱类型语言中的问题)是:
- 如果在检索 属性 之前忘记设置初始值,它将崩溃
- 如果您在 属性 名称中输入错误,它将崩溃
- 如果您在设置名称时有错别字,它将默默地无法更改所需的属性。
Kotlin 使将属性委托给 Map 成为可能的原因是,尽管它通常是一种反模式,但它在处理运行时动态数据(例如 JSON 时可以使用,您可能会转换回来和在 class 表示之间。
data class Person private constructor(
var name: ObservableField<String> = ObservableField("Tony Starks"),
var age: ObservableField<Int> = ObservableField(40),
var gender: ObservableField<String> = ObservableField("Male"),
var test: String = "Tony Starks",
) {
operator fun set(key: String, value: String) {
// Tried this approach but it didn't work.
this[key] = value
}
}
我要实现的是这个;
val person = Person()
person['test'] = "James Bond"
我已经能够用 PHP
实现同样的事情class Person {
private $name;
private $age;
private $gender;
public __get($key) {
return $this[$key];
}
public __set($key, $value) {
$this[$key] = $value;
}
}
可以在 Kotlin 中实现吗?
这种行为在像 Kotlin 这样的强类型语言中是一种反模式。通常明智的做法是不要试图强制强类型语言表现得像弱类型语言。使用强类型语言时,您的整个思维和设计方式应该有所不同。
就是说,可以通过将 class 设为 MutableMap 并将 delegating the relevant properties 设为自身来获得类似的语法。您可以通过委托(如下所示)或通过 subclassing HashMap 使其成为 MutableMap。但是,如果您使用 属性 代表,则不能将其设为 data class
。
class Person: MutableMap<String, Any?> by mutableMapOf() {
var test: String by this
init {
test = "Tony Stark"
}
override fun toString() = "Person(test='$test')"
}
fun main() {
val person = Person()
println(person)
person["test"] = "Pepper Potts"
println(person)
person.test = "Happy Hogan"
println(person["test"])
}
/** Prints:
Person(test='Tony Stark')
Person(test='Pepper Potts')
Happy Hogan
*/
这样做的缺点(类似于弱类型语言中的问题)是:
- 如果在检索 属性 之前忘记设置初始值,它将崩溃
- 如果您在 属性 名称中输入错误,它将崩溃
- 如果您在设置名称时有错别字,它将默默地无法更改所需的属性。
Kotlin 使将属性委托给 Map 成为可能的原因是,尽管它通常是一种反模式,但它在处理运行时动态数据(例如 JSON 时可以使用,您可能会转换回来和在 class 表示之间。