繁体   English   中英

在java代码中定义Kotlin扩展函数

[英]Define Kotlin extension function in java code

我想要一个 Kotlin 字符串扩展函数,它只能在MyParent类的继承者中MyParent (受保护的函数)。 MyParent类是用 java 编写的,不能转换为 Kotlin。 是否可以在 Java 代码中定义一个可以用作 Kotlin 代码中的扩展函数的方法?

我想我期待某种适当的签名,或者一些神奇的 @ThisIsExtenstionFunction 注释。

事实上,你可以。 非开箱即用,但有可能;)

让我们考虑这个例子。

首先,在Java中创建一个类MyParent

public class MyParent {
}

并且,在这个接口中定义扩展方法:

interface MyParentExt {
    fun String.ext(importantParam: Int)
}

所以,让MyParent实现这个接口。

public class MyParent implements MyParentExt {

    @NonNull
    @Override
    public String ext(@NonNull String $receiver, int importantParam) {
        // do cool stuff
        return $receiver;
    }

    // For testing let's add other public method:
    public String ext(int importantParam) {
        return "Kotlin > Java";
    }

}

那么,让我们来看看我们可以在孩子身上做些什么:

// Java child:
public class MyJavaChild extends MyParent {
    MyJavaChild() {
        "Java xD".ext(0); // Invalid! There is no such a method!
        ext("Java xD", 0); // Valid call for extension function
        ext(0); // Just Valid ;)
    }
}

// Kotlin class:
class MyGreatKotlinChild : MyParent() {
    init {
        "Kotlin is cool".ext(0) // Valid extension function!
        ext("Kotlin is cool", 0) // Invalid call. There is no method with such a signature!
        ext(0) // Valid.
    }
}

因此,我们可以使用语言指定的符号在 Java 和 Kotlin 中访问我们的扩展方法。

作为您的要求之一,您希望保护此方法。 不幸的是,接口方法的可见性始终是公开的。 因此,您仍然应该能够在成员上调用此函数。

但是...让我们来看看它实际上是如何工作的;)

// Java
public class Test {
    public static void main(String[] args) {
        MyChild child = new MyChild();

        // Both methods are valid
        child.ext("Java...", 0);
        child.ext(0);
    }
}

// Kotlin
fun main() {
    child.ext(0) // Normal function, valid call.
    child.ext("It actually works...", 0) // Hah, no way ;)

    // Just to be sure:
    "String".ext(0) // Nope, this ext method is visible for only class scope.
}

此外,您的父类只能扩展ParentOfMyParent类,您可以在其中定义扩展方法:

// Kotlin
abstract class ParentOfMyParent {
    protected abstract fun String.ext()
}

// Java
public class Parent extends ParentOfMyParent {
    @Override
    protected void ext(@NotNull String $receiver) {
    }
}

// Kotlin-child
class Child : Parent() {
    init {
        "".ext()
    }
}

// Java-child
public class ChildJava extends Parent {
    ChildJava() {
        ext("");
    }
}

这种方式方法具有想要的可见性。

没有这样的注释。

但是,编译器会发出可能包含此信息的 kotlin 元数据注释,但 j 不建议尝试诱使编译器认为某些类是 kotlin 源而不是 java 源。 更多信息: https : //kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/index.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM