Как я могу реализовать KFunctionN в Kotlin? - PullRequest
0 голосов
/ 12 февраля 2019

Если я определю

class MyF : KFunction0<Int> {
    override val name: String = "f"
    override fun invoke() = 42

    override val annotations: List<Annotation>
        get() = TODO()
    ....
}

Я могу написать

val f0: KFunction0<Int> = MyF()
assertEquals("f", f0.name)

, но если я попытаюсь

assertEquals(42, f0())

, я получу java.lang.ClassCastException: MyF cannot be cast to kotlin.jvm.functions.Function0

Как я могу определить свою собственную реализацию KFunction0?

Я не могу работать с () -> Int, потому что мне нужно свойство name.

Я использую Kotlin 1.3.21.

Дополнительно - кажется, что я могу запустить

val f02 = MyF()
assertEquals(42, f02())

Мой реальный вариант использования Могу ли я преобразовать Kotlin KFunction1 в KFunction0, применив аргумент?

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Определенно не стоит явно реализовывать внутренний класс из JVM Kotlin.У вас нет завершения кода для этих классов в IntelliJ или Android Studio по причине

Вместо этого вы можете использовать вызываемые ссылки, чтобы компилятор Kotlin генерировал все необходимые классы для вас.https://kotlinlang.org/docs/reference/reflection.html#callable-references

    fun myfun() = 42
    val kFunction = ::myfun


    println(kFunction.name)
    println(kFunction())

Преимущество - будущая версия Kotlin вряд ли нарушит этот код (и может нарушить ваш класс-наследник)

Если вам потребуется более длинное имя для функции, выможет объявить это так

fun `my function with long name`() = 43
0 голосов
/ 12 февраля 2019

В Kotlin 1.2 я не нашел KFunction0<T>, но только KFunction<T>, и я смог сделать то, что вы хотели:

import kotlin.reflect.*
import kotlin.test.assertEquals

class MyKF : KFunction<Int>{ // In Kotlin 1.3 you can extend KFunction0<Int>

    override val annotations: List<Annotation>
        get() = listOf()
    override val isAbstract: Boolean
        get() = false
    override val isExternal: Boolean
        get() = false
    override val isFinal: Boolean
        get() = true
    override val isInfix: Boolean
        get() = false
    override val isInline: Boolean
        get() = false
    override val isOpen: Boolean
        get() = false
    override val isOperator: Boolean
        get() = false
    override val isSuspend: Boolean
        get() = false
    override val parameters: List<KParameter>
        get() = listOf()
    override val typeParameters: List<KTypeParameter>
        get() = listOf()

    /**
     * I am not sure how get proper return type. So... This KFunction will return kotlin.Number.
     */
    override val returnType: KType
        get() = Int::class.supertypes[0]
    override val visibility: KVisibility?
        get() = KVisibility.PUBLIC

    override fun call(vararg args: Any?): Int {
        return 0
    }

    override fun callBy(args: Map<KParameter, Any?>): Int {
        return 0
    }

    override val name: String
        get() = "f"

    // Sience Kotlin 1.3
    override fun invoke(): Int {
        return 0
    }
}

fun main(args: Array<String>) {
    val kf = MyKF()
    assertEquals("f", kf.name)
    assertEquals(0, kf.call())

    println(kf.returnType)
    println(kf.name)
    println(kf.call())
    pritnln(kf.invoke())
}

Я обновлю Kotlin до 1,3 позже, и я завершумой ответ (если он работает в Kotlin 1.3).

Так где может быть ваша проблема?Может быть (просто удачное предположение) проверить тип на основе переопределенных методов, таких как returnType?

Редактировать:

После перехода на Kotlin 1.3 я смог расширить KFunction0<Int> вместо KFunction<Int>.Единственные изменения - мой класс также должен переопределить invoke(): Int.Все еще работает!

Edit2:

Я не уверен, что я просто не видел KFunction0 в моей IDE или отсутствует в Kotlin ниже 1.3.

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