[Kotlin] 泛型实例化

在 Kotlin 中,由于泛型的强化,以及阻止擦除等特性的存在,使得泛型实例化成为了可能,因此我们可以写出类似于以下的函数:

fun  new(): T

在 Java 中要实现这类函数无疑是困难的。那么下面来看一下 Kotlin 具体要怎么做吧,首先我们必须阻止泛型擦除:

inline fun  new(): T

通过 inlinereifiied 可以保证泛型类型被实化,这是实例化的基础,接着就可以写以下代码:

inline fun  new(): T {
    val clz = T::class.java
    val mCreate = clz.getDeclaredConstructor()
    mCreate. isAccessible = true
    return mCreate. newInstance()
}

这就是最基础的泛型实例化了,然鹅我们经常会遇到需要带参构造的情况,没有参数的构造只能满足一小部分情况,所以加个参数吧:

inline fun  new(vararg params: Any): T {
    val clz = T::class.java
    val paramTypes = params.map { it::class.java }.toTypedArray()
    val mCreate = clz.getDeclaredConstructor(*paramTypes)
    mCreate. isAccessible = true
    return mCreate. newInstance(* params)
}

那么有了这个函数之后,可以做些什么呢?比如说在 swing 下进行 UI 组件的实例化(其实就是想把代码写成 SwiftUI 2333):

fun button(text: String, block: JButton.() -> Unit) = new(text).also(block)

fun main(args: Array) {
    button("Click") {
        addActionListener { ... }
    }
}

好了,下面开始炫技:

inline fun  new(vararg params: Any) =
    T::class.java.getDeclaredConstructor(*params.map { it::class.java }.toTypedArray()).apply { isAccessible = true }.newInstance(*params)

以上代码作用于 JVM 端,包括 Android 都可以使用,如果是 Kotlin/Native 下使用,可以这么来:

inline fun new(block: T.() -> Unit): T = memScoped { alloc().also(block) }

于是我们可以在 macostarget 下,写这样的代码:

val sz = new {
    width = 0.0
    height = 0.0
}

这样就初始化了一个 CGSize 对象。

你可能感兴趣的:([Kotlin] 泛型实例化)