До того как я изучил Scala, я в основном использовал Java и Python для повседневной разработки. По моим впечатлениям, я не делал намеренного различия между методами и функциями. Это похоже на то, как в повседневной жизни мы не проводим специально различие между массой и весом. Однако они действительно различаются, и эти различия основаны на связи между ними!
Как определить
Сначала обратимся к оригинальному английскому тексту, чтобы увидеть различия и связи в их определениях:
A Тип функции — это (грубо говоря) тип вида (T1, ..., Tn) => U, который является сокращением для трейта FunctionN в стандартной библиотеке. Анонимные функции и значения методов имеют типы функций, и типы функций могут использоваться как часть объявлений и определений значений, переменных и функций. Фактически, он может быть частью типа метода.
A Тип метода — это тип, не имеющий значений. Это означает, что не существует никакого значения — ни объекта, ни экземпляра — с типом метода. Как упоминалось выше, Значение метода фактически имеет тип функции. Тип метода — это def объявление — всё, что касается def кроме его тела.
Пример:
scala> def m1(x:Int) = x+3 m1: (x: Int)Int scala> val f1 = (x: Int) => x+3 f1: Int => Int = <function1>
Видите? Определения методов и функций уже показаны в сигнатуре парсера Scala. `def m1(x: Int) = x+3` — это простое определение метода. В сигнатуре `m1: (x: Int)Int` указывает, что метод m1 имеет параметр x типа Int, а его возвращаемое значение — Int.
`val f1 = (x: Int) => x+3` — это определение функции. В сигнатуре парсера `f1: Int => Int = <function1>` указывает, что тело метода функции f1 принимает параметр типа Int, а тип выходного результата — Int.
Из приведённого выше примера можно сделать вывод:
Метод — это логический блок операций, начинающийся с `def` и имеющий список параметров (который может отсутствовать), как метод-член в объекте или классе.
Функция — это анонимный метод (со списком параметров или без него), присвоенный переменной (или константе), и представляет собой выражение, использующее символ преобразования `=>`, за которым следует логический блок кода. Логический блок кода после символа преобразования `=>` записывается так же, как тело метода.
Другие различия
Метод может появляться как часть выражения (вызов функции и передача параметров), но метод (метод с параметрами) не может быть конечным выражением. Метод без параметров может, но это становится вызовом метода, поскольку Scala позволяет опускать круглые скобки при вызове метода без аргументов. Функция может появляться как конечное выражение.
scala> m1
<console>:12: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
m1
^
scala> f1
res1: Int => Int = <function1>
У метода может не быть списка параметров, или список параметров может быть пустым. Однако у функции должен быть список параметров (который также может быть пустым). Имя метода подразумевает вызов метода, тогда как имя функции просто представляет саму функцию:
scala> def m2 = 100;
m2: Int
scala> def m3() = 1000;
m3: ()Int
scala> var f2 = => 100;
<console>:1: error: illegal start of simple expression
var f2 = => 100;
^
scala> var f2 =()=> 100;
f2: () => Int = <function0>
scala> m2
res2: Int = 100
scala> m3
res3: Int = 1000
scala> m3()
res4: Int = 1000
scala> f2
res5: () => Int = <function0>
scala> f2()
res6: Int = 100
Там, где ожидается функция, мы можем предоставить метод.
Это потому, что если мы предоставляем метод там, где ожидается функция, метод будет автоматически преобразован в функцию. Такое поведение называется ETA-расширением.
Примечание:
Там, где ожидается функция, мы можем использовать метод.
Там, где функция не ожидается, метод не будет автоматически преобразован в функцию.
В Scala операторы интерпретируются как методы:
- Префиксный оператор: `op obj` интерпретируется как `obj.op`
- Инфиксный оператор: `obj1 op obj2` интерпретируется как `obj1.op(obj2)`
- Постфиксный оператор: `obj op` интерпретируется как `obj.op`
scala> val ml = List(1,2,3,4) ml: List[Int] = List(1, 2, 3, 4) scala> ml.map((x)=>2*x) res0: List[Int] = List(2, 4, 6, 8) scala> def m(x:Int) = 2*x m: (x: Int)Int scala> ml.map(m) res1: List[Int] = List(2, 4, 6, 8) scala> def m(x:Int) = 3*x m: (x: Int)Int scala> ml.map(m) res2: List[Int] = List(3, 6, 9, 12)
Можно добавить знак подчеркивания после имени метода, чтобы принудительно превратить его в функцию.
Примечание:Между именем метода и знаком подчеркивания должен быть как минимум один пробел!
scala> def m3(x: Int): Int = x * x * x
m3: (x: Int)Int
scala> val f3 = m3_
<console>:10: error: not found: value m3_
val f3 = m3_
^
scala> val f3 = m3 _
f3: Int => Int = <function1>
scala> f3(3)
res0: Int = 27
Исходный URL: https://www.cnblogs.com/shihuc/p/5082701.html