Методы расширения в Java возможны без нарушения двоичной обратной совместимости? - PullRequest
0 голосов
/ 27 января 2020

Некоторые языки имеют методы расширения, такие как C#, Ruby, Smalltalk, Kotlin, Scala. Идея состоит в том, что вы можете добавить методы в класс, который закрыт для расширения, такого как системные классы, такие как String, Integer, или конечные классы, такие как ArrayList.

Таким образом, вместо того, чтобы иметь все эти Util-классы, вы просто добавляете соответствующий метод расширения. Поэтому вместо StringUtils.split (...) вы бы назвали "foo" .split ().

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

В C# и Kotlin методы расширения реализованы как методы stati c. Таким же образом, для Java был бы некоторый дополнительный синтаксис для StringUtils.split (...), который сообщал бы компилятору Java, что "foo" .split () во время компиляции должен быть заменен на StringUtils.split (...). По крайней мере, я думаю, что это то, что происходит в C# и Kotlin.

Опять же, мой вопрос заключается только в том, могут ли методы расширения в Java выполняться без обратной совместимости или нет. Только это.

1 Ответ

0 голосов
/ 27 января 2020

Я не знаю окончательного ответа на этот вопрос, но вот как Kotlin делает это, что, вероятно, было бы возможно и для Java.

Давайте рассмотрим простое расширение для String:

fun String.lengthSquare() = length * length

Компилятор Kotlin генерирует байт-код, подобный следующему (показан как соответствующий код Java):

public static final int lengthSquare(@NotNull String $this$lengthSquare) {
   Intrinsics.checkParameterIsNotNull($this$lengthSquare, "$this$lengthSquare");
   return $this$lengthSquare.length() * $this$lengthSquare.length();
}

Таким образом, в основном он просто создает метод stati c это принимает String, как мы знаем это из служебных методов. Я считаю, что Java компилятор может сделать что-то подобное. Все сайты вызовов этих функций расширения, конечно, будут использовать этот метод stati c в байтовом коде JVM.

Дополнительная информация о Kotlin Расширения

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

...