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

fun new(): T

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

inline fun new(): T

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

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) }

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

val sz = new {

width = 0.0

height = 0.0

}

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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐