Ошибка компиляции, вызывающая метод расширения из другого метода расширения в Котлине

Когда я пытаюсь вызвать метод расширения из другого метода расширения (перегружая этот метод), он не компилируется в IntelliJ 14.1.5 и Kotlin 0.14.449

Поскольку я новичок в языке, и в ссылке он не запрещает это делать, мне хотелось бы знать:

  • Можно ли вызвать метод расширения из другого метода расширения?
  • Является ли синтаксис, который я использую правильно (и, следовательно, это ошибка)?
  • Если нет, то какой правильный синтаксис?

Это код, который не компилируется:

fun String.replace (prefix: String, suffix: String, vararg parameters: Pair<String, String>) = parameters.fold(this, { result, pair -> result.replace (prefix + pair.first + suffix, pair.second) }) fun String.replace (vararg parameters: Pair<String, String>) = this.replace ("", "", parameters) 

Заранее спасибо!

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

    • При передаче одного varargs в другой вам нужно использовать оператор spread, потому что varargs принимаются как массив, вы хотите преобразовать их обратно в список параметров, и оператор spread делает именно это.

    • Звонок внутри fold() лямбда случайно называет себя. Поскольку вы вызываете string.replace() с двумя параметрами, какая версия выигрывает? Версия string.replace(String, String, vararg Pair<String,String>) или string.replace(String, String, Boolean[defaulted to false]) ? Оба они выглядят одинаково, когда только вызываются с двумя параметрами. И побеждает местный, и поэтому у вас есть рекурсия. Чтобы принудительно вызвать функцию замены stdlib, третий параметр по умолчанию имеет значение false поэтому передайте это значение специально, чтобы найти правильную сигнатуру метода.

    Рабочий код:

     fun String.replace(prefix: String, suffix: String, vararg parameters: Pair<String, String>) { parameters.fold(this) { result, pair -> // add a last parameter to differentiate what version I want called, the one with optional // boolean parameter last (ignoreCase: Boolean = false). Otherwise this recurses on accident. result.replace(prefix + pair.first + suffix, pair.second, false) } } fun String.replace(vararg parameters: Pair<String, String>) { this.replace ("", "", *parameters) // add * spread operator } 

    Ваша проблема в том, что первое String.replace рекурсивно вызывает себя, а первичное String.replace никогда не достигается. Кроме того, vararg во втором передается первому как Array>, поэтому вызов второй функции никогда не будет соответствовать первому.

     fun String.replace(vararg parameters: Pair<String, String>) = this.replace("", "", parameters) fun String.replace(prefix: String, suffix: String, parameters: Array<out Pair<String, String>>) = parameters.fold(this, { result, pair -> result.replace(prefix + pair.first + suffix, pair.second) }) 

    Поскольку я, хотя это была ошибка, я искал в трекер-пробник Kotlin и нашел это: https://youtrack.jetbrains.com/issue/KT-2079

    Правильный синтаксис для передачи аргумента vararg другой функции – это звездочка '*':

     fun String.filter (prefix: String, suffix: String, vararg parameters: Pair<String, String>) = parameters.fold(this, { result, pair -> result.replace (prefix + pair.first + suffix, pair.second) }) fun String.filter (vararg parameters: Pair<String, String>) = this.filter("", "", *parameters)