我想创建一个带有接收类类型的参数的泛型函数,例如:
class Foo{
var name = "Foooo"
}
class Liii{
var name = "Liii"
}
通用函数:
fun genericFunc(objects: Any, objectType: KClass<*>) {
print((objects as objectType).name) //This is not exist how to do this?
}
并这样称呼它:
val foo = Foo()
genericFun(foo, Foo::class)
val liii = Liii()
genericFun(liii, Liii::class)
它以这种方式迅速存在...
func genericFunc(objects: Any, objectType: Object.type) {
print((objects as objectType).name)
}
let foo = Foo()
genericFun(foo, Foo.self)
答案 0 :(得分:3)
首先,只有Class具有.name
变量。老实说,我看不到您在这里做什么的意义。如果只需要名称,则可以直接执行objects::class.java.name
。如果要使用KClass,则需要使用simpleName
或qualifiedName
。类还具有simpleName
,packageName
,typeName
和canonicalName
。这也意味着您需要上课。如果您绝对想投射它,则需要分别用KClass
或Class
重新获得::class
或::class.java
。
另外,请注意:我不确定在Swift中打印的工作方式,但是在Kotlin和Java中,它不会打印新行。我之所以这样说是因为我知道Python之类的某些语言具有print
或System.out.println
之类的println
函数。但是,print
不会自动创建换行符。
昨天我实际上偶然发现了这个确切的问题:如果我将KClass传递给函数,则无法传递whatever as kClass
,因为找不到它。显然,您无法执行此操作。 as
和is
采用类名,而不是Class
或KClass
的实例。
现在,您有两个选择,两个都使用泛型。
第一个仍在通过课程:
fun <T : Any> genericFunc(objects: Any, objectType: KClass<out T>) {
println(objectType.java.cast(objects))
}
如果要打印名称,则必须获得我前面提到的类。这一点也没有意义,因为您可以执行以下操作:
println(objects::class.java.name)
或者如果您绝对必须先进行转换(尽管我建议先使用isInstance
进行检查):
println(objectType.java.cast(objects)::class.java.name)
但是,如果代码不是重点,那就继续吧。
另一种使用归一化类型。在这里您可以使用as
:
inline fun <reified T : Any> genericFunc(objects: Any) {
print(objects as T)
}
最后一个叫法不同:
genericFunc<SomeClass>(instance);
但是; 这并不安全。我强烈建议您先检查类型。对于第一个,使用objectType.isInstance(objects)
,对于第二个,您可以仅使用is
。否则,如果类型不匹配,则可能会遇到ClassCastException的风险。
此外,根据您打算对其进行处理,还可以完全使用泛型:
fun <T> genericFunc(objects: T) {
// Do whatever
}
(可选)具有泛型类型的约束。