Kotlin - автоматически сопоставлять переопределенные функции - PullRequest
0 голосов
/ 25 июня 2019

Я пытаюсь написать функцию, которая, по сути, является методом-оболочкой для некоторых других функций, например, для некоторой функции ведения журнала.

Я пробовал несколько комбинаций inline, generic, reified и т. Д., Но, похоже, ничего не работает.

Моя функция выглядит так:

fun log(note: String, block: () -> Unit): () -> Unit {
    print(note)
    return block
}

Моя идея здесь состоит в том, чтобы выполнить некоторую простую операцию над входящим note, а затем просто вернуть ту входящую функцию, которая будет использоваться в том виде, в котором она была изначально.

Однако я хочу сделать это вокруг переопределенных функций, например так:

override fun onClick(clicked: View) = log("Green Button") {
    // here the regular onClick functionality goes
}

Здесь я получаю сообщение об ошибке " Тип возвращаемого значения () -> Unit, который не является подтипом переопределенного ". Это имеет смысл, так как сигнатуры функций не совпадают.

Однако, когда я делаю это с другими случайными функциями:

fun test() = log("foo") { ... }
fun otherTest(a: String, b: Int) = log("bar") { ... }

Я не получаю ошибок, и интерпретатор почему-то, кажется, хорошо с этим. Я также попытался взглянуть на что-то вроде GlobalScope.launch, чтобы принять такой подход, но я не мог понять это.

Возможно ли то, что я пытаюсь сделать? Если нет, то есть что-нибудь близкое?

Ответы [ 3 ]

0 голосов
/ 25 июня 2019

Я думаю

inline fun log(note: String, block: () -> Unit): Unit {
    print(note)
    return block()
}

должен делать то, что вы хотите.Его можно обобщить до

inline fun <T> log(note: String, block: () -> T): T {
    print(note)
    return block()
}

Я не получаю ошибок, и интерпретатор почему-то кажется, что с этим все в порядке.

Почему это удивительно?Эти функции просто возвращают () -> Unit.Если вы, например, наберете

fun test() = log("foo") { print("bar") }

, то при вызове test() не будет напечатано bar;звонить test()() будет.

0 голосов
/ 25 июня 2019

Когда вы используете оператор = для присвоения чего-либо fun, выражение в правой части должно возвращать тип возврата этого fun

Оригинал fun onClick(clicked:View) : Unit имеет тип возврата Unit. Когда ты пишешь

override fun onClick(clicked:View) = ..., ... - это то, что вы получаете, когда звоните onClick(v), поэтому оно должно быть Unit вместо View -> Unit (даже () -> Unit, как в вашем коде)

Возьмите более простой пример. Допустим, у вас есть fun sum(a:Int,b:Int) : Int. Когда вы пишете override fun sum(a:Int,b:Int) = ..., ... должно быть Int вместо (Int,Int) -> Int, так как вы ожидаете получить Int сразу при вызове sum(a,b). Если вы как-то получили, скажем,

val someOtherWayToSum : (Int,Int) -> Int = {...}

и хотите использовать его, вы можете написать

override fun sum(a:Int,b:Int) = someOtherWayToSum(a,b)

В вашем случае вам лучше просто сделать

override fun onClick(clicked:View){
    /* some operation (e.g your log)*/
    /* the regular onClick functionality */
}

поскольку вы переопределяете его и в любом случае реализуете его обычную функциональность.

0 голосов
/ 25 июня 2019

Скажите, если мое понимание неверно.Это мой подход

Функция расширения:

fun View.onClickWithLog(str: String, l: () -> Unit) {
    setOnClickListener { Log.d("LogTag", str); run(l) }
}

Использование (от Activity):

btnTest.onClickWithLog("My Button String"){
            Log.d("Actions from Activity", "Content")
            finish()
        }

и вывод

 D/LogTag: My Button String
 D/Actions from Activity: Content

, который печатает вашу заметку первым и выполняет действия в лямбда-выражении.

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