scala_函数和方法的区别

Scala中函数和方法的区别

方法可以作为一个表达式的一部分出现(调用函数并传递参数),但是方法不能作为最终的表达式。函数可以作为最终的表达式出现

//定义一个方法
scala> def m(x: Int) = 2*x
m: (x: Int)Int

//定义一个函数
scala> val f = (x: Int) => 2*x
f: Int => Int = <function1>

//方法不能作为最终表达式出现
scala> m
<console>:9: error: missing arguments for method m;
follow this method with `_' if you want to treat it as a partially applied function
              m
              ^
//函数可以作为最终表达式出现
scala> f
res9: Int => Int = <function1>

无参方法可以作为最终表达式出现,其实这属于方法调用,scala规定无参函数的调用可以省略括号

scala> def m1()=1+2
m1: ()Int

scala> m1
res10: Int = 3

参数列表对于方法是可选的,但是对于函数是强制的

方法可以没有参数列表,参数列表也可以为空。但是函数必须有参数列表(也可以为空)

//方法可以没有参数列表
scala> def m2=100
m2: Int

//方法可以有空的参数列表
scala> def m3()=100
m3: ()Int

//函数必须有参数列表,否则报错
scala> val f1 = =>100
<console>:1: error: illegal start of simple expression
       val f1 = =>100
                ^
//函数也可以有一个空的参数列表
scala> var f2 = () => 100
f2: () => Int = <function0>

方法为什么可以没有参数列表呢?

方法名意味着方法调用,函数名只是代表函数自身

因为方法不能作为最终的表达式存在,所以如果你写了一个方法的名字并且该方法不带参数(没有参数列表或者无参)

该表达式的意思是:调用该方法得到最终的表达式。因为函数可以作为最终表达式出现,如果你写下函数的名字,函数

调用并不会发生,该方法自身将作为最终的表达式进行返回,如果要强制调用一个函数,你必须在函数名后面写()

//该方法没有参数列表
scala> m2
res11: Int = 100

//该方法有一个空的参数列表
scala> m3
res12: Int = 100

//得到函数自身,不会发生函数调用
scala> f2
res13: () => Int = <function0>

//调用函数
scala> f2()
res14: Int = 100

为什么在函数出现的地方我们可以提供一个方法

在scala中很多高级函数,如map()filter()等,都是要求提供一个函数作为参数,但是我们也可以提供一个方法,像下面这样

scala> val myList = List(3,56,1,4,72)
myList: List[Int] = List(3, 56, 1, 4, 72)

//map()参数是一个函数
scala> myList.map((x) => 2*x)
res15: List[Int] = List(6, 112, 2, 8, 144)

//尝试给map()函数提供一个方法作为参数
scala> def m4(x:Int) = 3*x
m4: (x: Int)Int

//正常执行
scala> myList.map(m4)
res16: List[Int] = List(9, 168, 3, 12, 216)

这是因为如果期望出现函数的地方为我们提供了一个方法的话,该方法就会自动被转换为函数。该行为被称为ETA expansion,这样的话使用函数会变得简单很多

//期望出现函数的地方,我们可以使用方法
scala> val f3:(Int)=>Int=m4
f3: Int => Int = <function1>

//不期望出现函数的地方,方法并不会自动转换为函数
scala> val v3=m4
<console>:8: error: missing arguments for method m4;
follow this method with `_' if you want to treat it as a partially applied function
       val v3=m4
              ^

利用这种特性,我们可以写出很简洁的代码

//10.<被解释为object.method,即整型的<的方法,所以该表达式是一个方法,会被解释成函数

scala> myList.filter(10.<)
warning: there were 1 deprecation warning(s); re-run with -deprecation for details
warning: there were 1 feature warning(s); re-run with -feature for details
res17: List[Int] = List(56, 72)

因为在scala中操作符被解释为方法。你也可以写成10<

如何强制把一个方法变成函数

可以再方法名后面加一个下划线强制变成函数,部分应用函数

scala> val f4 = m4 _
f4: Int => Int = <function1>

scala> f4(2)
res18: Int = 6

传名参数是一个方法

传名参数实质是一个没有参数列表的方法。正是因此你才可以使用名字调用而不用添加()

//使用了两次x,意味着进行了两次方法调用
scala> def m1(x: => Int)=List(x,x)
m1: (x: => Int)List[Int]

scala> import util.Random
import util.Random

scala> val r = new Random()
r: scala.util.Random = scala.util.Random@45292ec1

//因为方法被调用了两次,所以两个值不相等
scala> m1(r.nextInt)
res19: List[Int] = List(-990906903, -1517453580)

如果你在方法体部分缓存了传名参数(函数),那么你就缓存了值(因为x函数被调用了一次)

scala> def m1(x: =>Int)={val y=x;List(y,y)}
m1: (x: => Int)List[Int]

scala> m1(r.nextInt)
res20: List[Int] = List(1994967723, 1994967723)

能否在函数体部分引用传名参数所代表的方法呢,是可以的(缓存的是传名参数所代表的方法)

scala> def m1(x: =>Int)={val y=x _;List(y(),y())}
m1: (x: => Int)List[Int]

scala> m1(r.nextInt)
res21: List[Int] = List(-1652190932, -185475502)
Scala中,函数(function)和方法(method)是有一些区别的。 1. 定义方式:函数是通过`val`关键字定义的值,而方法是通过`def`关键字定义的类成员。 2. 形式:函数是一个独立的值,可以直接赋值给变量,作为参数传递给其他函数,或者作为返回值返回。方法则是属于类或对象的成员,需要通过实例或者类名来调用。 3. 参数列表:函数的参数列表可以用括号包裹,也可以省略括号。方法的参数列表总是需要用括号包裹。 4. 调用方式:函数可以直接使用参数列表调用,而方法需要通过对象或者类名来调用。 5. 带有副作用:函数通常是纯函数(pure function),即没有副作用的函数方法可以有副作用,例如修改对象的状态或者打印输出等。 下面是一个示例来说明函数方法区别: ```scala // 定义函数 val add: (Int, Int) => Int = (x, y) => x + y // 定义类,并定义一个方法 class MyClass { def multiply(x: Int, y: Int): Int = x * y } // 创建类的实例 val obj = new MyClass() // 调用函数 val result1 = add(3, 4) println(result1) // 输出: 7 // 调用方法 val result2 = obj.multiply(3, 4) println(result2) // 输出: 12 ``` 需要注意的是,Scala方法可以转换为函数,而函数不能直接转换为方法。可以使用方法引用(method reference)或者使用下划线(_)来将方法转换为函数。例如: ```scala val multiplyFunc: (Int, Int) => Int = obj.multiply val multiplyFunc2: (Int, Int) => Int = obj.multiply _ ``` 总的来说,函数方法Scala中有些许的差异,但在实际使用中,它们可以互相转换和配合使用,根据需要选择合适的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值