Kotlin: универсальная функция с параметром класса типа, как Swift с Object.type - PullRequest
0 голосов
/ 09 ноября 2018

Я хочу создать обобщенную функцию с параметром, который получает тип класса, например:

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)

1 Ответ

0 голосов
/ 09 ноября 2018

Прежде всего, только класс имеет переменную .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
}

Опционально с ограничениями для универсального типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...