scala中方法和函数的区别

scala中方法和函数的区别


qq_遁去的一_1
浏览 1152回答 2
2回答

杨__羊羊

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先缓存起来,结果就会跟以前大不一样。 

慕沐林林

部分应用函数和偏函数是无关的。经常把部分应用函数(Partial Applied Function)和偏函数(Partial Function) 搞混。总结如下:部分应用函数(Partial Applied Function)是缺少部分参数的函数,是一个逻辑上概念偏函数是只对函数定义域的一个子集进行定义的函数。 scala中用scala.PartialFunction[-T, +S]类来表示比如定义了一个函数:def sum(x: Int)(y: Int) = x + y, 当调用sum的时候,如果不提供所有的参数或某些参数还未知时,比如sum _ , sum(3)(_: Int), sum(_: Int)(3), 这样就生成了所谓的部分应用函数。部分应用函数只是逻辑上的一个表达,scala编译器会用Function1, Function2这些类来表示它.下面这个变量signal引用了一个偏函数val signal: PartialFunction[Int, Int] = {case x if x > 1 => 1case x if x < -1 => -1}这个signal所引用的函数除了0值外,对所有整数都定义了相应的操作。 signal(0) 会抛出异常,因此使用前最好先signal.isDefinedAt(0)判断一下。 偏函数主要用于这样一种场景:对某些值现在还无法给出具体的操作(即需求还不明朗),也有可能存在几种处理方式(视乎具体的需求);我们可以先对需求明确的部分进行定义,比如上述除了0外的所有整数域,然后根据具体情况补充对其他域的定义,比如 :val composed_signal: PartialFunction[Int,Int] = signal.orElse{case 0 => 0}composed_signal(0) // 返回 0或者对定义域进行一定的偏移(假如需求做了变更, 1 为无效的点)val new_signal: Function1[Int, Int] = signal.compose{case x => x - 1}new_signal(1) // throw exceptionnew_signal(0) // 返回 -1new_signal(2) // 返回 1还可以用andThen将两个相关的偏函数串接起来val another_signal: PartialFunction[Int, Int] = {case 0 => 0case x if x > 0 => x - 1case x if x < 0 => x + 1}val then_signal = another_signal andThen signal这里的then_signal 剔除了-1, 0, 1三个点的定义
打开App,查看更多内容
随时随地看视频慕课网APP