【问题标题】:Define Kotlin extension function in java code在java代码中定义Kotlin扩展函数
【发布时间】:2019-07-11 11:07:26
【问题描述】:

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

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

【问题讨论】:

    标签: java kotlin extension-function


    【解决方案1】:

    其实可以的。非开箱即用,但有可能;)

    让我们考虑这个例子。

    首先,在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";
        }
    
    }
    

    那么,让我们看看我们可以在 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.
        }
    }
    

    因此,我们可以使用语言指定的符号在 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("");
        }
    }
    

    这种方式方法具有所需的可见性。

    【讨论】:

    • 啊哈,好吧,这可能是一个选项 :) 不幸的是,我将无法应用抽象类变体,因为 MyParent 已经有一个超类型,但例如谢谢。跨度>
    • 为什么会有问题?只需将 ParentOfMyParent 设为 parentOf(MyParent) 的子类型。我的意思是,类似:OldParent <-- MyParentExtensions <-- MyParent
    【解决方案2】:

    没有这样的注释。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-02
      • 1970-01-01
      • 2018-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-21
      相关资源
      最近更新 更多