[英]Kotlin - How to make a property delegate by map with a custom name?
I'm trying to get my head around property delegates, and I have an interesting use case. 我试图让我的头脑周围的财产代表,我有一个有趣的用例。 Is it possible to have something like this: 有可能有这样的事情:
class MyClass {
val properties = mutableMapOf<String, Any>()
val fontSize: Any by MapDelegate(properties, "font-size")
}
That would allow me to store fontSize
using the map as a delegate, but with a custom key (ie "font-size"). 这将允许我使用地图作为委托存储fontSize
,但使用自定义键(即“font-size”)。
The specific use case if for storing things like CSS property tags that can be accessed through variables ( fontSize
) for use in code, but can be rendered properly when iterating through the map ( font-size: 18px;
). 具体用例如果用于存储CSS属性标签之类的东西,可以通过变量( fontSize
)访问以便在代码中使用,但可以在迭代地图时正确呈现( font-size: 18px;
)。
The documentation on the delegated properties is a good source of information on the topic. 委托属性的文档是有关该主题的良好信息来源。 It probably is a bit longer read than the following examples: 它可能比以下示例读取时间长一些:
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")
}
You can ease up things a little bit and avoid typing the CSS property name by converting Kotlin property names to CSS attributes equivalents like so: 您可以稍微简化一下,避免键入CSS属性名称,方法是将Kotlin属性名称转换为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)
}
The above sample uses Guava's CaseFormat
. 上面的示例使用了Guava的CaseFormat
。
If you'd like to have mutable property your delegate will have to implement setter method: 如果您想拥有可变属性,您的委托必须实现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)]
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.