以下是演示此问题的最小示例:
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中做到这一点。 String
和Base
似乎都没有extension
方法。
答案 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()) }
}
在with(...) { ... }
块中,c
成为隐式接收器,因此允许您将其用作C
成员扩展中的调度接收器。这适用于使用带接收器的函数类型的任何其他函数:apply
,run
,use
等。
在您的情况下,它将是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')
}