Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
631 views
in Technique[技术] by (71.8m points)

kotlin - How do I call extension methods from outside the class they are defined in?

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 }} ...")
    }
}

Calling the extension method from Java is trivial:

Base o = new Derived();
o.extension("hello world", 'l');

But I can't figure out how to do it in pure Kotlin. Neither String nor Base seems to have the extension method.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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

(runnable demo of this code)

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.

In your case, it would be with(o) { "hello world".extension('l') }

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()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...