Kotlin - 如何使用自定义名称通过地图制作 属性 委托?
Kotlin - How to make a property delegate by map with a custom name?
我正在努力了解 属性 代表,我有一个有趣的用例。是否可以有这样的东西:
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any by MapDelegate(properties, "font-size")
}
这将允许我使用地图作为委托来存储 fontSize
,但使用自定义键(即 "font-size")。
具体用例 if 用于存储诸如 CSS 属性 标签之类的东西,这些标签可以通过变量 (fontSize
) 访问以在代码中使用,但可以在迭代时正确呈现通过地图(font-size: 18px;
).
the delegated properties 上的文档是有关该主题的良好信息来源。它可能比下面的例子要长一点:
fun <T, TValue> T.map(properties: MutableMap<String, TValue>, key: String): ReadOnlyProperty<T, TValue> {
return object : ReadOnlyProperty<T, TValue> {
override fun getValue(thisRef: T, property: KProperty<*>) = properties[key]!!
}
}
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any by map(properties, "font-size")
}
您可以通过将 Kotlin 属性 名称转换为 CSS 等价属性来稍微简化一些事情并避免键入 CSS 属性 名称:
fun <T, TValue> map(properties: Map<String, TValue>, naming:(String)->String): ReadOnlyProperty<T, TValue?> {
return object : ReadOnlyProperty<T, TValue?> {
override fun getValue(thisRef: T, property: KProperty<*>) = properties[naming(property.name)]
}
}
object CamelToHyphen : (String)->String {
override fun invoke(camelCase: String): String {
return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, camelCase)
}
}
fun <T, TValue> T.cssProperties(properties: Map<String,TValue>) = map(properties, CamelToHyphen)
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any? by cssProperties(properties)
}
上面的例子使用了Guava的CaseFormat
。
如果你想要可变 属性 你的委托将必须实现 setter 方法:
fun <T, TValue> map(properties: MutableMap<String, TValue?>, naming: (String) -> String): ReadWriteProperty<T, TValue?> {
return object : ReadWriteProperty<T, TValue?> {
override fun setValue(thisRef: T, property: KProperty<*>, value: TValue?) {
properties[naming(property.name)] = value
}
override fun getValue(thisRef: T, property: KProperty<*>) = properties[naming(property.name)]
}
}
我正在努力了解 属性 代表,我有一个有趣的用例。是否可以有这样的东西:
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any by MapDelegate(properties, "font-size")
}
这将允许我使用地图作为委托来存储 fontSize
,但使用自定义键(即 "font-size")。
具体用例 if 用于存储诸如 CSS 属性 标签之类的东西,这些标签可以通过变量 (fontSize
) 访问以在代码中使用,但可以在迭代时正确呈现通过地图(font-size: 18px;
).
the delegated properties 上的文档是有关该主题的良好信息来源。它可能比下面的例子要长一点:
fun <T, TValue> T.map(properties: MutableMap<String, TValue>, key: String): ReadOnlyProperty<T, TValue> {
return object : ReadOnlyProperty<T, TValue> {
override fun getValue(thisRef: T, property: KProperty<*>) = properties[key]!!
}
}
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any by map(properties, "font-size")
}
您可以通过将 Kotlin 属性 名称转换为 CSS 等价属性来稍微简化一些事情并避免键入 CSS 属性 名称:
fun <T, TValue> map(properties: Map<String, TValue>, naming:(String)->String): ReadOnlyProperty<T, TValue?> {
return object : ReadOnlyProperty<T, TValue?> {
override fun getValue(thisRef: T, property: KProperty<*>) = properties[naming(property.name)]
}
}
object CamelToHyphen : (String)->String {
override fun invoke(camelCase: String): String {
return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, camelCase)
}
}
fun <T, TValue> T.cssProperties(properties: Map<String,TValue>) = map(properties, CamelToHyphen)
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any? by cssProperties(properties)
}
上面的例子使用了Guava的CaseFormat
。
如果你想要可变 属性 你的委托将必须实现 setter 方法:
fun <T, TValue> map(properties: MutableMap<String, TValue?>, naming: (String) -> String): ReadWriteProperty<T, TValue?> {
return object : ReadWriteProperty<T, TValue?> {
override fun setValue(thisRef: T, property: KProperty<*>, value: TValue?) {
properties[naming(property.name)] = value
}
override fun getValue(thisRef: T, property: KProperty<*>) = properties[naming(property.name)]
}
}