Scala中既有函数也有方法 大多数情况下都可以不去理会他们之间的区别。但是有时候必须要了解他们之间的不同。
Scala 中的方法跟 Java 的方法一样 方法是组成类的一部分。方法有名字、类型签名 有时方法上还有注解 以及方法的功能实现代码(字节码)。
Scala 中的函数是一个完整的对象。Scala 中用 22 个特质(trait)抽象出了函数的概念。这 22 特质从 Function1 到 Function22:
如上图中的 Function10 代表的是:有 10 个形参 返回值为 R(协变)的函数。
Scala 中的函数其实就是继承了这些 Trait 的类的对象 如:通过函数字面量定义一个函数
其实上述函数的定义方式跟如下定义方式等同:
由于 Function2 是特质 不能直接 new。上述 new Function2[Int,Int,Int](){} 其实是定义并实例化一个实现了 Function2 特质的类的对象。
apply 是 scala 中的语法糖:对一个对象 obj 上调用 obj() scala 编译器会转换为 obj.apply();在一个类 clazz 上调用 clazz(),scala 编译器会转换为 clazz_company_obj.apply() 其中 clazz_company_obj 为 clazz 的伴生对象。
具体的差异 总结为如下几点:
1.方法不能作为单独的表达式而存在(参数为空的方法除外) 而函数可以。如:
在如上的例子中 首先定义了一个方法 m 接着有定义了一个函数f。接着把函数名(函数值)当作最终表达式来用 由于f本身就是
一个对象(实现了 FunctionN 特质的对象) 所以这种使用方式是完全正确的。但是把方法名当成最终表达式来使用的话 就会出错。
2.函数必须要有参数列表 而方法可以没有参数列表
在如上的例子中 m1方法接受零个参数 所以可以省略参数列表。而函数不能省略参数列表
3.方法名是方法调用 而函数名只是代表函数对象本身
这个比较容易理解。因为保存函数字面量的变量(又称为函数名或者函数值)本身就是实现了 FunctionN 特质的类的对象 要调用对象的 apply方法 就需要使用obj()的语法。所以函数名后面加括号才是调用函数。如下:
4.在需要函数的地方 如果传递一个方法 会自动进行ETA展开(把方法转换为函数)
如果直接把一个方法赋值给变量会报错。如果指定变量的类型就是函数 那么就可以通过编译 如下:
当然也可以强制把一个方法转换给函数 这就用到了 scala 中的部分应用函数:
5.传名参数本质上是个方法
传名参数实质上是一个参数列表为空的方法 如下:
如上代码实际上定义了一个方法 m1 m1 的参数是个传名参数(方法)。由于对于参数为空的方法来说 方法名就是方法调用 所以List(x,x)实际上是进行了两次方法调用。
由于 List(x,x) 是进行了两次方法调用 所以得到两个不同的值。
如果稍微修改一下函数的m1的定义 把x先缓存起来 结果就会跟以前大不一样。
原文:https://blog.csdn.net/u012302488/article/details/50543661
尊贵的董事大人
英文标题不为空时 视为本栏投稿
需要关键字 描述 英文标题