Как обратиться к внешней функции из лямбды? - PullRequest
0 голосов
/ 02 сентября 2018

Вопрос в комментарии. Я хочу обратиться к внешней функции append, а не к той, которая определена в StringBuilder, как мне это сделать?

fun append(c: Char) {
    println("TEST")
}

fun sbTest() = with(StringBuilder()) {
    for(c in 'A'..'Z') {
        append(c) // how do I refer to the append function declared above?
    }
    toString()
}

Я знаю, что могу ввести ссылочную переменную функции, например:

val f = ::append

и позвоните f вместо append, но есть ли другой способ?

Ответы [ 2 ]

0 голосов
/ 02 сентября 2018

Вы также можете использовать функцию расширения вместо with(), например .let{...}. Это отправит StringBuilder в качестве аргумента функции расширения как it (кстати, вы можете переименовать его в любое другое место):

fun sbTest() = StringBuilder().let{ it ->
    for(c in 'A'..'Z') {
        // using string builder
        it.append(c)
        // using your function
        append(c) 
    }
    it.toString()
}

Функция .let{...} возвращает ваш последний оператор, он же String из toString(), поэтому ваша исходная функция все равно будет возвращать его правильно. Вместо этого другие функции могут возвращать this, например .also{...}

Я склонен использовать функции расширения, а не with(), поскольку они более гибкие.

Смотрите этот пост, чтобы освоить функции расширения: https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84

РЕДАКТИРОВАТЬ: Получил also{} и let{} перепутал. Я переключил их

0 голосов
/ 02 сентября 2018

Проблема в том, что все, что вызывается в with, затеняет внешние функции, потому что введено this. Та же проблема возникает, если у вас есть класс и функция верхнего уровня с функцией с одинаковой сигнатурой.

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

На методы верхнего уровня может ссылаться пакет в Kotlin, например, com.some.package.method. Он также может быть импортирован как таковой, что является наиболее распространенным способом сделать это. Существует очень мало методов, которые называются com.some.package.method().

Kotlin, как и Python, допускает as в импорте. Это означает, что вы можете сделать это:

package com.example;

// This is the important line; it declares the import with a custom name.
import com.example.append as appendChar; // Just an example name; this could be anything ***except append***. If it's append, it defeats the purpose

fun append(c: Char) {
    println("TEST")
}

fun sbTest() = with(StringBuilder()) {
    for(c in 'A'..'Z') {
        appendChar(c) 
    }
    toString()
}

В качестве альтернативы, как я уже говорил, вы можете добавить пакет:

for(c in 'A'..'Z') {
    com.example.append(c) 
}

val f = ::append, конечно, тоже вариант, в любом случае переименовать функцию все же проще, чем создавать импорт с as или константами, если у вас есть доступ к функции (и что она не принадлежит зависимость).


Если ваш файл находится за пределами пакета, что я не рекомендую вам делать, вы можете просто объявить импорт как:

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