偶尔,我发现了一个有趣的案例类功能。 foo需要一个3 Int到case类的函数,代码如下:
case class Whatever(a: Int, b: Int, c: Int)
def foo(f: (Int, Int, Int) => Whatever) = f(1,2,3).c
foo(Whatever) //compilation fine, scala complier is powerful ...........
如果Whatever是普通类,很明显,编译将会失败。
有人可以解释为什么案例类可以这样使用,我怀疑它是工厂应用方法的原因,但我不确定。另外,如果它是普通类,是否可以将它作为案例类使用。
答案 0 :(得分:3)
scala编译器为case类生成一个伴随对象并实现一些东西(实现AbstractFunction3,apply,unapply):
javap Whatever\$.class
Compiled from "Test.scala"
public final class Whatever$ extends scala.runtime.AbstractFunction3<java.lang.Object, java.lang.Object, java.lang.Object, Whatever> implements scala.Serializable {
public static final Whatever$ MODULE$;
public static {};
public final java.lang.String toString();
public Whatever apply(int, int, int);
public scala.Option<scala.Tuple3<java.lang.Object, java.lang.Object, java.lang.Object>> unapply(Whatever);
public java.lang.Object apply(java.lang.Object, java.lang.Object, java.lang.Object);
}
答案 1 :(得分:3)
正如@planetenkiller所提到的,如果你创建一个case类,编译器会自动生成一个带有几种方法的伴随对象。
它特别实现apply
和unapply
,允许您执行以下操作:
val x = Whatever(1,2,3) // is actually Whatever.apply(1,2,3)
x match {
case Whatever(x,y,z) => // uses Whatever.unapply
/* ... */
}
此外,它使用正确数量的参数扩展FunctionN
。因此,案例类的伴随对象是函数。因此,很明显你可以将它用作一个函数(即一次,在调用网站上没有魔法)。
val x: Function3[Int, Int, Int, Whatever] = {
Whatever // compiles, no implicit conversion
}
答案 2 :(得分:0)
感谢@planetenkiller @ gzm0的解释,所以如果我想要正常的类有相同的行为。这是实施。
class Whatever(a: Int, b: Int, c: Int)
object Whatever extends ((Int, Int, Int) => Whatever) {
def apply(a: Int, b: Int, c: Int): Whatever = {
new Whatever(a, b, c)
}
}
def foo(f: (Int, Int, Int) => Whatever) = f(1,2,3)
foo(Whatever)