Kotlin:泛型函数,具有类似Swift的Object.type类型的参数



我想创建一个具有接收类类型的参数的泛型函数,例如:

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,则需要使用simpleNamequalifiedName。类还有simpleNamepackageNametypeNamecanonicalName。这也意味着你需要上课。如果你绝对想投射它,你需要分别用::class::class.java重新获得KClassClass

另外,请注意:我不确定Swift中的print是如何工作的,但在Kotlin和Java中,它不会打印新行。我之所以提到这一点,是因为我知道像Python这样的一些语言的print函数像System.out.printlnprintln一样工作。但是,print不会自动创建新行。


事实上,我昨天偶然发现了这个问题:如果我将KClass传递给函数,我就不能传递给whatever as kClass,因为它找不到。显然,你不能这样做。asis采用类名,而不是ClassKClass的实例。

现在,您有两个选项,这两个选项都使用泛型。

第一个仍在通过考试:

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
}

(可选(具有泛型类型的约束。

最新更新