如何从它们定义的类之外调用扩展方法?
这是一个演示问题的最小示例:
Here is a minimal example that demonstrates the problem:
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 调用扩展方法很简单:
Calling the extension method from Java is trivial:
Base o = new Derived();
o.extension("hello world", 'l');
但我不知道如何在纯 Kotlin 中做到这一点.String
和 Base
似乎都没有 extension
方法.
But I can't figure out how to do it in pure Kotlin. Neither String
nor Base
seems to have the extension
method.
首先要注意一个定义为成员的扩展函数需要两个接收者,一个是封闭类的实例(dispatch receiver,通常是封闭类的this
),另一个是函数扩展的类型的实例(扩展接收者).这被记录在此处.
First, note that an extension function defined as a member requires two receivers, one is an instance of the enclosing class (dispatch receiver, usually this
of the enclosing class) and the other is the instance of the type that the function extends (extension receiver). This is documented here.
因此,要从类外部调用这样的函数,您必须提供两个接收器.Kotlin 没有任何语法可以像 (x, "abc").stringExtension()
,但您可以使用 扩展 lambda:
So, to call such a function from outside the class you have to provide two receivers. Kotlin doesn't have any syntax to do that explicitly like (x, "abc").stringExtension()
, but you can provide the dispatch receiver implicitly using an 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
等.
In the with(...) { ... }
block, c
becomes the implicit receiver, thus allowing you to use it as a dispatch receiver in C
member extensions. This would work with any other function that uses functional types with receivers: apply
, run
, use
etc.
在您的情况下,它将是 with(o) { "hello world".extension('l') }
In your case, it would be with(o) { "hello world".extension('l') }
正如 @KirillRakhman 所述,C
扩展函数的扩展接收器也可以隐式地用作 C
中定义的扩展的调度接收器:
As @KirillRakhman noted, an extension receiver of an extension function for C
can also be implicitly used as a dispatch receiver for the extensions defined inside C
:
fun C.someExtension() = "something".extended()