Определить функцию расширения Kotlin в коде Java - PullRequest
2 голосов
/ 11 июля 2019

Я хотел бы иметь функцию расширения Kotlin для строки, которая доступна только в наследниках класса MyParent (защищенная функция).MyParent класс написан на Java и не может быть преобразован в Kotlin.Можно ли определить метод в коде Java, который можно использовать в качестве функции расширения в коде Kotlin?

Я думаю, что ожидаю какую-то правильную подпись или какую-то волшебную аннотацию @ThisIsExtenstionFunction.

Ответы [ 2 ]

2 голосов
/ 11 июля 2019

На самом деле, вы можете.Не из коробки, но это возможно;)

Давайте рассмотрим этот пример.

Сначала создайте класс MyParent в Java

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, используя обозначение, указанное в lang.

В качестве одного из ваших требований вы хотели, чтобы этот метод был защищен.К сожалению, видимость методов интерфейса всегда общедоступна.Итак, вы все еще должны иметь возможность вызывать эту функцию для члена.

Но ... Давайте проверим, как она на самом деле работает;)

// 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("");
    }
}

Этот метод имеет желаемую видимость.

0 голосов
/ 11 июля 2019

Такой аннотации нет.

Тем не менее, компилятор генерирует аннотации метаданных kotlin, которые могут содержать эту информацию, но j не рекомендует пытаться обманом заставить компилятор думать, что какой-то класс является источником kotlin, а не источником java,Дополнительная информация: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/index.html

...