为什么case类可以用作参数中的函数

时间:2014-08-21 06:42:53

标签: function scala functional-programming case-class

偶尔,我发现了一个有趣的案例类功能。 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是普通类,很明显,编译将会失败。

有人可以解释为什么案例类可以这样使用,我怀疑它是工厂应用方法的原因,但我不确定。另外,如果它是普通类,是否可以将它作为案例类使用。

3 个答案:

答案 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类,编译器会自动生成一个带有几种方法的伴随对象。

它特别实现applyunapply,允许您执行以下操作:

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)