我如何从定义的课堂外部调用扩展方法



这是一个最小示例,证明了问题:

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方法。

首先,请注意,定义为成员的扩展函数需要两个接收器,一个是封闭类的实例( dispatch接收器,通常是封闭的 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()) }
}

(此代码的可运行演示)

with(...) { ... }块中,c成为隐式接收器,因此您可以将其用作C成员扩展中的调度接收器。这将适用于将功能类型与接收器一起使用的任何其他功能:applyrunuse等。

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

正如@kirillrakhman所指出的那样,C的扩展功能的扩展接收器也可以隐式用作C内定义的扩展程序的调度接收器:

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

要使用它在类外部使用扩展方法,您应该在类中实现它,您应该这样做:

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

希望这对您有帮助。

您的扩展功能仅在基本/派生类内部定义。请参阅声明的扩展名为会员。

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

最新更新