Function 什么';这两种结构的根本区别是什么?
可能重复:Function 什么';这两种结构的根本区别是什么?,function,scala,anonymous-function,Function,Scala,Anonymous Function,可能重复: scala>valx1:(Int)=>Int=(x)=>x+1 x1:(Int)=>Int= scala>defx2(x:Int)=x+1 x2:(Int)Int scala>x1(1) res0:Int=2 scala>x2(1) res1:Int=2 x1和x2之间的实际差异是什么。你能举例说明什么时候使用这两种结构吗?在Scala中,这两种结构从用户的角度看很相似,但从JVM的角度看却完全不同x1是一个“函数对象”,而x2是一个方法 代码示例 方法 在Scala中,def定
scala>valx1:(Int)=>Int=(x)=>x+1
x1:(Int)=>Int=
scala>defx2(x:Int)=x+1
x2:(Int)Int
scala>x1(1)
res0:Int=2
scala>x2(1)
res1:Int=2
x1和x2之间的实际差异是什么。你能举例说明什么时候使用这两种结构吗?在Scala中,这两种结构从用户的角度看很相似,但从JVM的角度看却完全不同
x1
是一个“函数对象”,而x2
是一个方法
代码示例
方法
在Scala中,def
定义了一个直接编译成JVM方法的方法,它必须属于某个Java类
在上面的代码片段中,x2
和x3
都被编译为JVM方法,并且属于类测试
,甚至x3
都是在方法(嵌套方法)中定义的
编译代码后,您可以使用javap-private Test
验证这一点。它将输出以下梅萨日:
brianhsu@USBGentoo ~/test $ javap -private Test
Compiled from "test.scala"
public class Test extends java.lang.Object implements scala.ScalaObject{
private final scala.Function1 x1;
public scala.Function1 x1();
public int x2(int);
private final int x3$1(int);
public Test();
}
您可以看到,x2
只是一个普通的Java方法,并且x3被重命名为x3$1(以避免在other method`中存在另一个x3
时出现名称冲突),但从JVM的角度来看,它仍然是一个普通的Java方法
函数对象
我使用这个术语是为了避免混淆,这是您用valx1=(x:Int)=>x+1
之类的东西定义的
当您使用它时,它可能看起来像方法,但实际上它与您使用def
s定义的方法完全不同
那么valx1=(x:Int)=>x+2
意味着什么
在Scala中,有一些特性称为Function0、Function1、Function2、Function3……Function22
它看起来都是这样的(我简化了它):
当您编写valx1=(x:Int)=>x+2
时,Scala编译器将生成一个实现trait函数1的对象,它可能如下所示:
val t = new Function1[Int, Int] {
def apply(t1: Int) = t1 + 2
}
当您编写x1(3)
时,实际上Scala只是将其转换为t.apply(3)
因此,函数对象不是方法,它只是一个普通的Java对象,它有一个名为apply
的方法,Scala编译器为您提供了一种语法糖,在使用它们时不必显式调用apply
您可以再次使用javap
来验证这一点
brianhsu@USBGentoo ~/test $ javap Test\$\$anonfun\$1
Compiled from "test.scala" public final class Test$$anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable{
public static final long serialVersionUID;
public static {};
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
public Test$$anonfun$1(Test);
}
brianhsu@USBGentoo ~/test $ javap -private Test
Compiled from "test.scala" public class Test extends java.lang.Object implements scala.ScalaObject{
private final scala.Function1 x1;
public scala.Function1 x1();
public int x2(int);
private final int x3$1(int);
public Test();
}
您会注意到有一个名为Test$$anonfun$1.class
的额外.class文件,它是(x:Int)=>x+2
的类,您会注意到有一个x1
私有变量,它是Function1
的类型,ax1()
方法返回scala.Function1
有x1()
方法,因为Scala实现了统一的访问原则。但是最重要的是x1()
方法只返回Test$$anonfun$1
类的函数对象实例
结论
也许方法和函数看起来是一样的,但它们是不同的东西。Scala编译器可以帮助我们不费吹灰之力地同时使用它们
大多数情况下,您不会关心它们之间的区别,但确实有时有些东西需要一个函数对象,而您只有方法
在这种情况下,编译器会告诉您,在方法名之后添加一个。
,将其提升到函数对象
更新
下面是一个有趣的代码示例,显示了方法和函数对象之间的差异:您可以定义一个包含25个参数的方法,但不能定义包含22个以上参数的函数对象
class Test2
{
def x (
x01: Int, x02: Int, x03: Int, x04: Int, x05: Int,
x06: Int, x07: Int, x08: Int, x09: Int, x10: Int,
x11: Int, x12: Int, x13: Int, x14: Int, x15: Int,
x16: Int, x17: Int, x18: Int, x19: Int, x20: Int,
x21: Int, x22: Int, x23: Int, x24: Int, x25: Int
) = 0
// Compile error:
// implementation restricts functions to 22 parameters
/*
val y = (
x01: Int, x02: Int, x03: Int, x04: Int, x05: Int,
x06: Int, x07: Int, x08: Int, x09: Int, x10: Int,
x11: Int, x12: Int, x13: Int, x14: Int, x15: Int,
x16: Int, x17: Int, x18: Int, x19: Int, x20: Int,
x21: Int, x22: Int, x23: Int, x24: Int, x25: Int
) => 0
*/
}
它的答案几乎涵盖了一切。我认为如果你把它看作是一种对象上的方法,这确实很有帮助,但我也能理解为什么有些人会不同意这种观点。更多的是:这个问题已经被问了很多次,但人们从来没有找到问题,因为他们不知道区别是什么,所以他们不知道如何提问。第一个是函数,第二个是方法。知道了这一点,就去读他们之间的区别。@Jonas,那是不对的
x1
是一个函数,x2
是一个方法。为什么要否决投票?我是否误解了他们之间的区别?
val t = new Function1[Int, Int] {
def apply(t1: Int) = t1 + 2
}
brianhsu@USBGentoo ~/test $ javap Test\$\$anonfun\$1
Compiled from "test.scala" public final class Test$$anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable{
public static final long serialVersionUID;
public static {};
public final int apply(int);
public int apply$mcII$sp(int);
public final java.lang.Object apply(java.lang.Object);
public Test$$anonfun$1(Test);
}
brianhsu@USBGentoo ~/test $ javap -private Test
Compiled from "test.scala" public class Test extends java.lang.Object implements scala.ScalaObject{
private final scala.Function1 x1;
public scala.Function1 x1();
public int x2(int);
private final int x3$1(int);
public Test();
}
class Test2
{
def x (
x01: Int, x02: Int, x03: Int, x04: Int, x05: Int,
x06: Int, x07: Int, x08: Int, x09: Int, x10: Int,
x11: Int, x12: Int, x13: Int, x14: Int, x15: Int,
x16: Int, x17: Int, x18: Int, x19: Int, x20: Int,
x21: Int, x22: Int, x23: Int, x24: Int, x25: Int
) = 0
// Compile error:
// implementation restricts functions to 22 parameters
/*
val y = (
x01: Int, x02: Int, x03: Int, x04: Int, x05: Int,
x06: Int, x07: Int, x08: Int, x09: Int, x10: Int,
x11: Int, x12: Int, x13: Int, x14: Int, x15: Int,
x16: Int, x17: Int, x18: Int, x19: Int, x20: Int,
x21: Int, x22: Int, x23: Int, x24: Int, x25: Int
) => 0
*/
}