ZetCode

Kotlin dynamic 关键字

最后修改于 2025 年 4 月 19 日

Kotlin 的 dynamic 关键字在主要是静态类型的语言中启用动态类型。它主要用于 JavaScript 互操作性。本教程通过实际例子探讨了 dynamic 关键字。

基本定义

Kotlin 中的 dynamic 关键字在编译时禁用类型检查。它主要用于从 Kotlin 处理 JavaScript。使用 dynamic,方法调用和属性访问在运行时而不是编译时解析。

动态基本用法

dynamic 最简单的用法是声明一个可以容纳任何类型的变量。编译器不会检查此变量的类型或方法调用。

BasicDynamic.kt
package com.zetcode

fun main() {

    val dyn: dynamic = "Hello"
    println(dyn.length) // Output: 5
    
    dyn = 42
    println(dyn.toFixed(2)) // Output: 42.00
}

在这里,我们声明一个 dynamic 变量,它首先保存一个字符串,然后保存一个数字。我们可以调用字符串方法和数字方法,而无需编译时检查。这些调用在运行时解析。

JavaScript 互操作性

dynamic 的主要用例是从 Kotlin 调用 JavaScript 代码。它允许与 JavaScript 的动态特性无缝交互。

JsInterop.kt
package com.zetcode

import kotlin.js.json

fun main() {

    val jsObject: dynamic = json(
        "name" to "John",
        "age" to 30,
        "address" to json(
            "street" to "Main St",
            "city" to "New York"
        )
    )
    
    println(jsObject.name) // Output: John
    println(jsObject.address.city) // Output: New York
}

此示例展示了如何在 Kotlin 中使用 JavaScript 对象。我们使用 json 创建一个嵌套的 JavaScript 对象,并动态访问其属性。编译器不会验证这些属性访问。

动态函数调用

使用 dynamic,您可以调用编译时不存在的函数。函数解析发生在运行时,类似于 JavaScript。

DynamicFunction.kt
package com.zetcode

fun main() {

    val calculator: dynamic = object {
        fun add(a: Int, b: Int) = a + b
    }
    
    println(calculator.add(5, 3)) // Output: 8
    println(calculator.multiply(5, 3)) // Runtime error
}

我们创建一个带有 add 函数的对象并成功调用它。multiply 调用在运行时失败,因为该函数不存在。这演示了动态解析的风险和灵活性。

动态属性访问

动态变量允许访问未在类中声明的属性。这在使用外部 JavaScript 库时很有用。

DynamicProperty.kt
package com.zetcode

class Person(val name: String)

fun main() {

    val person: dynamic = Person("Alice")
    println(person.name) // Output: Alice
    println(person.age) // Output: undefined (no error)
    
    person.age = 30 // Dynamically add property
    println(person.age) // Output: 30
}

在这里,我们访问已声明 (name) 和未声明 (age) 的属性。使用 dynamic,我们甚至可以在运行时添加新属性,就像在 JavaScript 中一样。编译器不会捕获这些动态属性访问。

动态数组

动态类型适用于数组,允许在 Kotlin 中通常会进行类型检查的灵活的数组操作。

DynamicArray.kt
package com.zetcode

fun main() {

    val arr: dynamic = arrayOf(1, 2, 3)
    println(arr.joinToString()) // Output: 1, 2, 3
    
    arr.push(4) // JavaScript-style array operation
    println(arr.joinToString()) // Output: 1, 2, 3, 4
    
    arr[0] = "one" // Change type of element
    println(arr.joinToString()) // Output: one, 2, 3, 4
}

此示例显示了 Kotlin 中的 JavaScript 风格的数组操作。我们使用 push 并动态更改元素的类型。这些操作在常规 Kotlin 数组中是不允许的。

动态与外部 JavaScript

调用外部 JavaScript 函数时,dynamic 对于处理 JavaScript API 的未类型化特性至关重要。

ExternalJs.kt
package com.zetcode

// Assume this is an external JavaScript function
external fun getJsData(): dynamic

fun main() {

    val data: dynamic = getJsData()
    println(data.message)
    data.showAlert("Hello from Kotlin")
}

此示例演示了如何调用返回动态对象的外部 JavaScript 函数。我们可以在编译时不知道其结构的情况下访问属性和调用方法。确切的行为取决于 JavaScript 代码。

使用 Dynamic 进行类型检查

即使使用 dynamic,您也可以使用 Kotlin 的类型检查运算符执行运行时类型检查。

DynamicTypeCheck.kt
package com.zetcode

fun main() {

    val value: dynamic = "Kotlin"
    
    if (value is String) {
        println(value.length) // Smart cast to String
    }
    
    when (value) {
        is String -> println("It's a string")
        is Number -> println("It's a number")
        else -> println("Unknown type")
    }
}

在这里,我们使用 is 检查来确定动态变量的运行时类型。当您执行显式类型检查时,Kotlin 的智能转换即使与动态变量一起使用也有效。这在使用动态代码时提供了一定的安全性。

动态类型的最佳实践

来源

Kotlin 动态类型文档

本教程深入介绍了 Kotlin 的 dynamic 关键字,展示了它在 JavaScript 互操作性中的主要用途。我们探讨了动态属性、方法、数组和类型检查。虽然功能强大,但应在 Kotlin 应用程序中谨慎使用动态类型。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有多年的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我写了 1400 多篇文章和 8 本电子书。我有超过八年的编程教学经验。

列出 所有 Kotlin 教程