如何从定义的类之外调用扩展方法?

时间:2017-03-12 11:42:28

标签: extension-methods kotlin

以下是演示此问题的最小示例:

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');

但我无法弄清楚如何在纯Kotlin中做到这一点。 StringBase似乎都没有extension方法。

3 个答案:

答案 0 :(得分:12)

首先,请注意,定义为成员的扩展函数需要两个接收器,一个是封闭类的实例(调度接收器,通常是封闭类的this)和另一个是函数扩展的类型的实例(扩展接收器)。记录在案here

因此,要从课外调用此类函数,您必须提供两个接收器。 Kotlin doesn't have any syntax明确表示(x, "abc").stringExtension(),但您可以使用extension 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 of this code)

with(...) { ... }块中,c成为隐式接收器,因此允许您将其用作C成员扩展中的调度接收器。这适用于使用带接收器的函数类型的任何其他函数:applyrunuse等。

在您的情况下,它将是with(o) { "hello world".extension('l') }

@KirillRakhman所述,C的扩展函数的扩展接收器也可以隐式用作C内定义的扩展的调度接收器:

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

答案 1 :(得分:1)

要使用它来解析课外的扩展方法,你应该 NOT 在一个类中实现它,你应该这样做:

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

希望这对你有所帮助。

答案 2 :(得分:0)

您的扩展功能仅在Base / Derived类中定义。请参阅Declaring Extensions as Members

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