我如何从定义类的外部调用扩展方法?
这是一个最小的例子,演示了这个问题:
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
方法。
首先请注意,定义为成员的扩展函数需要两个接收者,一个是封闭类的实例( 调度接收者 ,通常是封闭类的实例),另一个是函数扩展类型的实例( 扩展接收者 )。 这是在这里记录 。
所以,要从课堂外调用这样一个功能,你必须提供两个接收器。 Kotlin 没有像(x, "abc").stringExtension()
那样显式的语法 , (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
成员扩展中的调度接收者。 这可以与任何其他使用接收器的函数类型的函数一起使用: 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 } }
希望这应该可以帮到你。