我想创建一个具有接收类类型的参数的泛型函数,例如:
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)
在swift中,它是这样存在的。。。
func genericFunc(objects: Any, objectType: Object.type) {
print((objects as objectType).name)
}
let foo = Foo()
genericFun(foo, Foo.self)
首先,只有class有一个.name
变量。老实说,我看不出你在这里做什么有什么意义。如果你只想要这个名字,你可以直接做objects::class.java.name
。如果要使用KClass,则需要使用simpleName
或qualifiedName
。类还有simpleName
、packageName
、typeName
和canonicalName
。这也意味着你需要上课。如果你绝对想投射它,你需要分别用::class
或::class.java
重新获得KClass
或Class
。
另外,请注意:我不确定Swift中的print是如何工作的,但在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
}
(可选(具有泛型类型的约束。