繁体   English   中英

Kotlin 如何创建动态 Object

[英]Kotlin How to create dynamic Object

在 javascript 我们可以做这样的事情

 function putritanjungsari(data){ console.log(data.name) } let data = { name:"putri", div:"m4th" } putritanjungsari(data)

In kotlin, i'am creating a function that accept an object as parameter then read it's properties later, how to do that in kotlin that targeting JVM?

如果我理解您的问题是正确的,那么您正在尝试使用一个变量将键与某个值或 undefined(null in kt) 相关联(如果没有找到)。 您正在寻找Map如果您不知道您想要什么类型,您可以制作任何类型的 map? 所以

Map<String, Any?>

这也是可以为空的

Map<String, Any>

如果你不想为空

您的代码例如:

fun putritanjungsari(data: Map<String, Any?>){
print(data["name"]) 
}

val data: Map<String, Any?> =mapOf(        
"name" to "putri",
"div" to "m4th" 
)
putritanjungsari(data)

请注意,您不能在此处添加新密钥或编辑任何数据,默认 map 是不可变的。 有 MutableMap (实现方式相同,只是它有一个放置新数据的方法)

您可以应用属性设计模式来解决您的问题。

这是它在 Kotlin 中的实现:

interface DynamicProperty<T> {
    fun cast(value: Any?): T
    fun default(): T

    companion object {
        inline fun <reified T> fromDefaultSupplier(crossinline default: () -> T) =
            object : DynamicProperty<T> {
                override fun cast(value: Any?): T = value as T
                override fun default(): T = default()
            }

        inline operator fun <reified T> invoke(default: T) = fromDefaultSupplier { default }

        inline fun <reified T> required() = fromDefaultSupplier<T> {
            throw IllegalStateException("DynamicProperty isn't initialized")
        }

        inline fun <reified T> nullable() = DynamicProperty<T?>(null)
    }
}

operator fun <T> DynamicProperty<T>.invoke(value: T) = DynamicPropertyValue(this, value)

data class DynamicPropertyValue<T>(val property: DynamicProperty<T>, val value: T)

class DynamicObject(vararg properties: DynamicPropertyValue<*>) {
    private val properties = HashMap<DynamicProperty<*>, Any?>().apply {
        properties.forEach { put(it.property, it.value) }
    }

    operator fun <T> get(property: DynamicProperty<T>) =
        if (properties.containsKey(property)) property.cast(properties[property])
        else property.default()

    operator fun <T> set(property: DynamicProperty<T>, value: T) = properties.put(property, value)
    operator fun <T> DynamicProperty<T>.minus(value: T) = set(this, value)
}

fun dynamicObj(init: DynamicObject.() -> Unit) = DynamicObject().apply(init)

您可以通过以下方式定义属性:

val NAME = DynamicProperty.required<String>() // throws exceptions on usage before initialization
val DIV = DynamicProperty.nullable<String>() // has nullable type String?
val IS_ENABLED = DynamicProperty(true) // true by default

现在您可以使用它们:

fun printObjName(obj: DynamicObject) {
    println(obj[NAME])
}

val data = dynamicObj {
    NAME - "putri"
    DIV - "m4th"
}
printObjName(data)

// throws exception because name isn't initialized
printObjName(DynamicObject(DIV("m4th"), IS_ENABLED(false)))

使用DynamicObject而不是Map<String, Any?>的原因:

  1. 类型安全( NAME - 3NAME(true)不会编译)
  2. 属性使用不需要强制转换
  3. 您可以定义未初始化属性时程序应执行的操作

您必须使用Any之后,您必须使用 object,像这样

private fun putritanjungsari(data : Any){
    if(data is Mydata){
        var data =  data as? Mydata
        data.name
    }
}

Kotlin 是静态类型语言,因此需要精确定义或明确推断参数类型(例如,Groovy 至少通过两种方式解决此问题)。 但是对于 JS 互操作性 Kotlin 提供了动态类型

同时,在您的特定情况下,您可以将数据结构键入 kt 的 Map 并且不要与严格的类型争论。

只是为了灵感。 在 Kotlin 中,您可以创建临时对象:

val adHoc = object {
    var x = 1
    var y = 2
}
println(adHoc.x + adHoc.y)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM