Как вызвать методы расширения вне класса, в котором они определены?

Вот минимальный пример, демонстрирующий проблему:

abstract class Base { abstract fun String.extension(x: Char) } class Derived : Base() { override fun String.extension(x: Char) { // Calling lots of methods on String, hence extension method println("${first()} $length ${last()} ${firstOrNull { it == x }} ...") } } 

Вызов метода расширения из Java тривиален:

 Base o = new Derived(); o.extension("hello world", 'l'); 

Но я не могу понять, как это сделать в чистом Котлине. Ни String ни Base похоже, не имеют метода extension .

    Во-первых, обратите внимание, что функция расширения, определенная как член, требует двух приемников, один – экземпляр класса-оболочки ( диспетчер-получатель , обычно this класс-класс), а другой экземпляр типа, который функция расширяет ( приемник расширения ). Это описано здесь .

    Таким образом, для вызова такой функции извне класса вам необходимо предоставить два приемника. У Kotlin нет синтаксиса, чтобы это явно (x, "abc").stringExtension() , но вы можете обеспечить приемник-получатель неявно с помощью расширения lambda :

     class C(val name: String) { fun String.extended() = this + " extended by " + name } fun main(args: Array<String>) { val c = C("c") with(c) { println("abc".extended()) } } 

    (runnable demo этого кода)

    В блоке with(...) { ... } , c становится неявным приемником, что позволяет использовать его в качестве приемника-получателя в расширениях членов C Это будет работать с любой другой функцией, которая использует функциональные типы с приемниками: apply , run , use и т. Д.

    В вашем случае это будет with(o) { "hello world".extension('l') }

    Как отметил @KirillRakhman , приемник расширения функции расширения для C также может быть неявно использован в качестве приемника отправки для расширений, определенных внутри C :

     fun C.someExtension() = "something".extended() 

    Функция расширения определяется только внутри класса Base / Derived. См. Декларация расширений в качестве членов .

     abstract class Base { abstract fun String.extension(x: Char) } class Derived : Base() { override fun String.extension(x: Char) { // Calling lots of methods on String, hence extension method println("${first()} $length ${last()} ${firstOrNull { it == x }} ...") } fun callExtension(c: Char) { "hello".extension(c) } } fun main(args: Array<String>) { val base = Derived() base.callExtension('h') } 

    Чтобы расшифровать метод расширения вне класса, используя его, вы НЕ должны внедрять его внутри класса, и вам нужно сделать следующее:

     package com.sample.test import java.io.File fun File.folderLength() : Long { return 0L } 

    Поэтому в вашем классе, который вызывает этот метод:

     package com.sample.util import com.sample.test.* import java.io.File class foo{ fun getFolderSize(url: String) : Long{ var file = new File("...") var length = file.folderLength() return length } } 

    Надеюсь, это поможет вам.

    Interesting Posts

    Как показать диалог «Прогресс» и «Отклонить»

    Порядок вычисления побитовых операторов в Котлине

    Не удается получить доступ к внутренним компонентам из тестового источника с помощью Android

    Как получить делегированный экземпляр в Котлин?

    Как я могу создать новую активность Android в Android Studio из проекта Explorer?

    Android Не удалось создать один или несколько классов

    Почему у kotlin есть функции componentN в классе данных, если у них уже есть геттеры и сеттеры?

    Как обратиться к лямбда изнутри?

    Это правильный способ бросить

    Как создать радиогруппу 2×2?

    Kotlin: set-ish setter, который возвращает «this»

    Spring Boot не запускает автозагрузчик при использовании @Cacheable

    Литералы класса Kotlin с пустой левой стороной еще не поддерживаются?

    Каков наилучший способ объявить компонент UI в Android с Kotlin?

    Gson или Moshi: в поле POJO может быть 2 типа, как сохранить в любом из полей

    Давайте будем гением компьютера.