38

ケースクラスを作成すると、コンパイラは、いくつかのケースクラスの機能を備えた対応するコンパニオンオブジェクトを作成します。applyプライマリコンストラクタ、、、、およびに一致するファクトリequalsメソッドhashCodeですcopy

奇妙なことに、この生成されたオブジェクトはFunctionNを拡張します。

scala> case class A(a: Int)                                 
defined class A

scala> A: (Int => A)
res0: (Int) => A = <function1>

これは、次の場合にのみ当てはまります。

  • 手動で定義されたコンパニオンオブジェクトはありません
  • パラメータリストは1つだけです
  • 型引数はありません
  • ケースクラスは抽象的ではありません。

このように約2年前に追加されたようです。最新の化身はここにあります。

誰かがこれを使用しますか、またはそれが追加された理由を知っていますか?静的フォワーダーメソッドを使用すると、生成されたバイトコードのサイズが少し大きくなり#toString()、コンパニオンオブジェクトのメソッドに表示されます。

scala> case class A()
defined class A

scala> A.toString
res12: java.lang.String = <function0>

アップデート

単一のapplyメソッドを使用して手動で作成されたオブジェクトは、自動的に次のように見なされませんFunctionN

object HasApply {
  def apply(a: Int) = 1
}
val i = HasApply(1)

// fails
//  HasApply: (Int => Int) 
4

4 に答える 4

48

ケースクラスコンパニオンオブジェクトがFunctionNを実装する理由は、以前は、ケースクラスがコンパニオンオブジェクトではなく、クラスとファクトリメソッドを生成したためです。Scalaにエクストラクタを追加したとき、ファクトリメソッドをapplyメソッドとunapplyメソッドを使用して完全なコンパニオンオブジェクトに変換する方が理にかなっています。ただし、ファクトリメソッドはFunctionNに準拠しているため、コンパニオンオブジェクトも準拠する必要がありました。

[編集]そうは言っても、コンパニオンオブジェクトを「関数」ではなく独自の名前として表示するのは理にかなっています

于 2010-06-16T14:25:59.720 に答える
11

さて、target.apply(a1, a2, a3 ... aN)Scalaでそれを考えると:

  1. によって砂糖漬けにすることができますtarget(a1, a2, a3 ... aN)
  2. によって実装する必要があるメソッドですFunctionN

コンパニオンオブジェクトは当然のようです。

object MyClass {
  def apply(a1 : A1, ... aN: AN) = new MyClass(a1, ..., aN)
}

本当に:

object MyClass extends FunctionN[A1, ... , AN, MyClass]{
  def apply(a1 : A1, ... aN: AN) = new MyClass(a1, ..., aN)
}

したがって、追加は私には自然なようです(なぜそれがあなたにとって「奇妙」に見えるのかわかりませんか?)。それが実際に何かを追加したかどうかについて。まあ、それは私より賢い人のためです!

于 2010-06-15T22:38:06.100 に答える
11

その自然さについてのoxbow_lakesの回答とは別に、コンストラクターをファーストクラスの関数として、特にScalaコレクションの高階関数と組み合わせて使用​​できると便利なことがよくあります。(些細な)例として、

scala> case class Foo(i : Int)
defined class Foo

scala> List(1, 2, 3) map Foo   
res0: List[Foo] = List(Foo(1), Foo(2), Foo(3))
于 2010-06-16T09:37:57.503 に答える
5
Welcome to Scala version 2.8.0.RC3 (Java HotSpot(TM) Client VM, Java 1.6.0_20).

scala> case class CC3(i: Int, b: Boolean, s: String)
defined class CC3

scala> CC3
res0: CC3.type = <function3>

scala> CC3.apply(1, true, "boo!")
res1: CC3 = CC3(1,true,boo!)

scala> CC3(1, true, "boo!")
res2: CC3 = CC3(1,true,boo!)
于 2010-06-15T22:19:08.830 に答える