简体   繁体   English

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

[英]Define Kotlin extension function in java code

I'd like to have a Kotlin extension function for string that is accessible only in inheritors of MyParent class (protected function).我想要一个 Kotlin 字符串扩展函数,它只能在MyParent类的继承者中MyParent (受保护的函数)。 MyParent class is written in java and cannot be converted to Kotlin. MyParent类是用 java 编写的,不能转换为 Kotlin。 Is it possble to define a method in java code that can be used as extension function in Kotlin code?是否可以在 Java 代码中定义一个可以用作 Kotlin 代码中的扩展函数的方法?

I think I expect some kind of proper signature, or some magic @ThisIsExtenstionFunction annotation.我想我期待某种适当的签名,或者一些神奇的 @ThisIsExtenstionFunction 注释。

Actually, you can.事实上,你可以。 Non out of box, but it is possible ;)非开箱即用,但有可能;)

Let's consider this example.让我们考虑这个例子。

First, create a class MyParent in Java首先,在Java中创建一个类MyParent

public class MyParent {
}

And, define extension method in this interface:并且,在这个接口中定义扩展方法:

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

So, let MyParent implement this interface.所以,让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";
    }

}

So, let's check what we can do in childs:那么,让我们来看看我们可以在孩子身上做些什么:

// 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.
    }
}

So, we can access our extension method in both, Java and Kotlin using lang-specified notation.因此,我们可以使用语言指定的符号在 Java 和 Kotlin 中访问我们的扩展方法。

As one of your requirements you wanted this method to be protected.作为您的要求之一,您希望保护此方法。 Unfortunately, visibility of interface methods is always public.不幸的是,接口方法的可见性始终是公开的。 So, you still should be able to call this function on a member.因此,您仍然应该能够在成员上调用此函数。

But... Let's check how does it actually works ;)但是...让我们来看看它实际上是如何工作的;)

// 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.
}

Also, your parent class just can extend ParentOfMyParent class where you would define your extension methods:此外,您的父类只能扩展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("");
    }
}

This way method has a wantned visibility.这种方式方法具有想要的可见性。

There is no such annotation.没有这样的注释。

However, the compiler emits kotlin metadata annotations that might contain this information, but j would not recommend trying to trick the compiler into thinking some class is kotlin source rather than java source.但是,编译器会发出可能包含此信息的 kotlin 元数据注释,但 j 不建议尝试诱使编译器认为某些类是 kotlin 源而不是 java 源。 More info: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/index.html更多信息: 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