Операторы Методы
Одним из наиболее очевидных различий между Java и Scala является то, что Scala поддерживает перегрузку операторов. Фактически, Scala поддерживает вариант перегрузки операторов, который намного сильнее, чем что-либо, предложенное C++, С# или даже Ruby. За очень немногими исключениями, любой символ может использоваться для определения пользовательского оператора. Это обеспечивает огромную гибкость в DSL и даже в среднем ежедневном API (например, List
и Map
).
Очевидно, что эта особенная языковая особенность не собирается переводить на Java так хорошо. Java не поддерживает перегрузки операторов любого вида, тем более сверхмощной формы, определенной в Scala. Таким образом, операторы Scala должны быть скомпилированы в совершенно несимвольную форму на уровне байт-кода, иначе взаимодействие Java будет непоправимо нарушено, а сама JVM не сможет усвоить результат.
Хорошим отправным пунктом для принятия решения о таком переводе является способ объявления операторов в Scala: как методы. Каждый оператор Scala (включая унарные операторы, такие как !
) Определяется как метод внутри класса:
abstract class List[+A] {
def ::[B >: A](e: B) = ...
def +[B >: A](e: B) = ...
}
Поскольку классы Scala становятся классами Java, а методы Scala становятся методами Java, наиболее очевидным переводом было бы использование каждого метода оператора и создание соответствующего метода Java с сильно переведенным именем. На самом деле, это именно то, что делает Scala. Приведенный выше класс скомпилируется в эквивалент этого кода Java:
public abstract class List<A> {
public <B super A> List<B> $colon$colon(B e) { ... }
public <B super A> List<B> $plus(B e) { ... }
}
Каждый допустимый символ в синтаксисе метода Scalas имеет соответствующий перевод вида " $trans
". Список поддерживаемых переводов - это одна из тех частей документации, которую вы ожидаете найти на веб-сайте Scala. Однако, увы, его нет. Ниже приводится таблица всех переводов, о которых я знаю:
┌────────────────┬─────────────┐
│ Scala Operator │ Compiles To │
├────────────────┼─────────────┤
│ = │ $eq │
├────────────────┼─────────────┤
│ > │ $greater │
├────────────────┼─────────────┤
│ < │ $less │
├────────────────┼─────────────┤
│ + │ $plus │
├────────────────┼─────────────┤
│ - │ $minus │
├────────────────┼─────────────┤
│ * │ $times │
├────────────────┼─────────────┤
│ / │ div │
├────────────────┼─────────────┤
│ ! │ $bang │
├────────────────┼─────────────┤
│ @ │ $at │
├────────────────┼─────────────┤
│ # │ $hash │
├────────────────┼─────────────┤
│ % │ $percent │
├────────────────┼─────────────┤
│ ^ │ $up │
├────────────────┼─────────────┤
│ & │ $amp │
├────────────────┼─────────────┤
│ ~ │ $tilde │
├────────────────┼─────────────┤
│ ? │ $qmark │
├────────────────┼─────────────┤
│ | │ $bar │
├────────────────┼─────────────┤
│ \ │ $bslash │
├────────────────┼─────────────┤
│ : │ $colon │
└────────────────┴─────────────┘
Используя эту таблицу, вы сможете получить "настоящее имя" любого оператора Scala, что позволяет использовать его изнутри Java. Конечно, идея будет заключаться в том, что Java действительно поддерживает перегрузку операторов и может напрямую использовать операторы Scalas, но я почему-то сомневаюсь, что это произойдет в ближайшее время.
**** Этот ответ был опубликован кем-то, но по какой-то причине удален (очень хотелось бы, если бы его владелец мог опубликовать его повторно)