通过反射调用构造函数与调用普通函数类似。通过反射调用构造函数也是使用 KFunction
实例,KFunction
实例可以通过两种方式获得:一种是函数引用;另外一种是通过 KClass
提供的 API 获得 KFunction
实例。
- 通过反射调用构造函数的示例代码如下:
class Rectangle(private var width: Int, private var height: Int) {
var area: Int = 0
init {
area = width * height
}
constructor(width: Int, height: Int, area: Int) : this(width, height) {
this.area = area;
}
constructor(area: Int) : this(200, 100) {
this.area = area
}
override fun toString(): String {
return "Rectangle(width=$width, height=$height, area=$area)"
}
}
fun main(args: Array<String>) {
val clz = Rectangle::class // 1️⃣
clz.constructors.forEach { println(it.name) } // 2️⃣
// 获得主构造函数对象
val ctor1 = clz.primaryConstructor // 3️⃣
val rect1 = ctor1?.call(100, 90) // 4️⃣
println(rect1)
// 获得第一个构造函数对象
val ctor2 = clz.constructors.first() // 5️⃣
val rect2 = when (ctor2.parameters.size) { // 6️⃣
3 -> ctor2.call(100, 3, 300)
2 -> ctor2.call(100, 2)
else -> ctor2.call(20000)
}
println(rect2)
val ctor3: (Int) -> Rectangle = ::Rectangle // 7️⃣
val rect3 = ctor3(20000) // 8️⃣
println(rect3)
}
运行结果:
<init>
<init>
<init>
Rectangle(width=100, height=90, area=9000)
Rectangle(width=100, height=3, area=300)
Rectangle(width=200, height=100, area=20000)
Process finished with exit code 0
上面代码声明了一个 Rectangle
类,它有三个构造函数:一个主构造函数,两个次构造函数。在 main
函数中代码第1️⃣行是声明 Rectangle
类引用。代码第2️⃣行中的 constructors
属性是获取 Rectangle
中所有的构造函数。代码第3️⃣行 primaryConstructor
属性是获得主构造函数,代码第4️⃣行是通过 call
函数调用主构造函数。
代码第5️⃣行从构造函数集合中取出第一个元素,由于不知道第一个构造函数有几个参数,所以通过代码第6️⃣行判断参数的个数,根据个数选中调用哪一个构造函数,parameters
属性返回构造函数的参数集合。
代码第7️⃣行 ::Rectangle
是引用构造函数,由于 Rectangle
类有三个构造函数,编译器不能确定 ::Rectangle
是引用哪一个构造函数,所以需要制定 ctor3
变量的类型,ctor3
变量应该声明为 KFunction
类型,但是需要提供泛型类型,比较麻烦,本例中 ctor3
变量声明为函数类型 (Int) -> Rectangle
,函数类型 与 KFunction
是兼容的。但需要注意的是使用函数类型声明的变量不能使用 call
函数调用,见代码第8️⃣行直接调用 ctor3
。
网友评论