Kotlin如何创建动态对象

时间:2019-10-03 07:03:36

标签: kotlin

在javascript中,我们可以执行以下操作

function putritanjungsari(data){
	console.log(data.name)
}

let data = {
	name:"putri",
	div:"m4th"
}
putritanjungsari(data)

在kotlin中,我正在创建一个接受对象作为参数的函数,然后稍后读取其属性,如何在kotlin中以JVM为目标呢?

5 个答案:

答案 0 :(得分:1)

如果我对您的问题的理解正确,那么您正在尝试使用一个变量,该变量将键与某个值或未定义(kt中为null)关联(如果找不到)。您正在搜索Map 如果您不知道想要什么类型,可以制作一个Any类型的地图。所以

foreach (RDPData rdp in root.Value)
{
    AxMsRdpClient9NotSafeForScripting rdpClient = new AxMsRdpClient9NotSafeForScripting();
    ((System.ComponentModel.ISupportInitialize)(rdpClient)).BeginInit();
    System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RDPMultiTabForm));
    rdpClient.Enabled = true;
    rdpClient.Name = rdp.Alias;
    rdpClient.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("rdpClient.OcxState")));
    TabPage tab = new TabPage(rdp.Alias);
    rdpClient.Dock = DockStyle.Fill;
    tab.Controls.Add(rdpClient);
    tab.Dock = DockStyle.Fill;
    tabControl1.TabPages.Add(tab);
    ((System.ComponentModel.ISupportInitialize)(rdpClient)).EndInit();
    rdpClient.Server = rdp.Server;
    rdpClient.UserName = rdp.User;
    rdpClient.AdvancedSettings7.EnableCredSspSupport = true;
    IMsTscNonScriptable secured = (IMsTscNonScriptable)rdpClient.GetOcx();
    secured.ClearTextPassword = rdp.Password;
    rdpClient.Connect();
}

哪些也是可空的

Map<String, Any?>

如果您不希望为空

例如,您的代码:

Map<String, Any>

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

答案 1 :(得分:0)

您必须使用Any,然后,必须像这样投射对象

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

答案 2 :(得分:0)

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

同时,在您的特殊情况下,您可以在kt的Map中键入 data 结构,而不必与严格的类型争论。

答案 3 :(得分:0)

您可以应用property design pattern来解决问题。

这是它在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. 您可以定义未初始化属性时程序应该做什么

答案 4 :(得分:-2)

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

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