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

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

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 } } 

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

    Intereting Posts
    Записать в значение парного нуля в kotlin MyObjectBox не генерируется в kotlin (библиотека объектов) Параметры аннотации Java в Котлине Получить коэффициенты чисел в Котлине Могу ли я создать метод расширения Kotlin для добавления rxJava-подписки на композитную подписку? Класс данных Котлина == Структура C #? Как инициализировать представление в классе фрагментов в котлин? Kotlin: Почему большинство переменных подчеркнуты в Android Studio и как отключить это? Работа Gradle работает на локальной машине, но не работает на сервере Jenkins CI? Абсолютный член не может получить доступ напрямую: Котлин Невозможно преобразовать в коллекцию в котлин В Kotlin, как я могу прочитать все содержимое InputStream в String? Файл spring-configuration-metadata.json не генерируется в IntelliJ Idea для класса Kotlin @ConfigurationProperties Цель камеры не работает: она входит в блок catch и говорит: «Не удалось создать файл!» Сохранить сторонний объект в ORM