Здесь я расскажу только номер 4.
Одна из вещей, которая отличает "замыкания" Java от замыканий, встречающихся в других языках, заключается в том, что они могут использоваться вместо интерфейса, который не описывает функцию- например, Runnable
.Это то, что подразумевается под SAM, Single Abstract Method.
Java делает это, потому что эти интерфейсы изобилуют в библиотеке Java, и они изобилуют в библиотеке Java , потому что Java была создана без типов функций или замыканий,В их отсутствие каждый код, который нуждался в инверсии управления, должен был использовать интерфейс SAM.
Например, Arrays.sort
принимает объект Comparator
, который будет выполнять сравнение элементов сортируемого массива.В отличие от этого, Scala может отсортировать List[A]
, получив функцию (A, A) => Int
, которая легко проходит через замыкание.Тем не менее, обратите внимание на примечание 1.
Итак, поскольку библиотека Scala была создана для языка с типами функций и замыканиями, нет необходимости поддерживать такую вещь, как замыкания SAM в Scala.
Конечно, существует вопрос о совместимости Scala / Java - хотя библиотеке Scala может не понадобиться что-то вроде SAM, библиотека Java делает это.Есть два пути, которые можно решить.Во-первых, поскольку Scala поддерживает замыкания и типы функций, очень легко создавать вспомогательные методы.Например:
def runnable(f: () => Unit) = new Runnable {
def run() = f()
}
runnable { () => println("Hello") } // creates a Runnable
На самом деле этот конкретный пример можно сделать еще короче, если использовать параметры по имени Scala, но это не относится к делу.Во всяком случае, это то, что, возможно, Java мог бы сделать вместо того, что он собирается делать.Учитывая преобладание интерфейсов SAM, это не так уж удивительно.
Другой способ, которым Scala справляется с этим, - неявные преобразования.Просто добавив implicit
к методу runnable
, приведенному выше, можно создать метод, который автоматически применяется (примечание 2), когда требуется Runnable
, но предоставляется функция () => Unit
.
Последствияоднако, очень уникальный и все еще спорный в некоторой степени.
Примечание 1 : На самом деле, этот конкретный пример был выбран с некоторой злобой ... Comparator
имеет два абстрактные методы вместо одного, в этом вся проблема.Поскольку один из его методов может быть реализован в терминах другого, я думаю, они просто «вычтут» методы защитника из абстрактного списка.
И, на стороне Scala, даже если есть метод сортировки, которыйиспользует (A, A) => Boolean
, а не (A, A) => Int
, стандартный метод сортировки вызывает объект Ordering
, который очень похож на Comparator
в Java!Однако в случае Scala Ordering
выполняет роль класса класса .
Примечание 2 : последствия автоматически применяются после того, как они былиимпортировано в сферу .