2011-12-15 9 views
5

::クラス(短所)が定義されているクラスListブック「Scalaでプログラミング」の第22章において

final case class ::[T](hd: T, tl: List[T]) extends List[T] { 
    //... 
} 

::方法のように定義される:

def ::[U >: T](x: U): List[U] = new scala.::(x, this) 

なぜnewfinalcaseclass ::のインスタンスを作成するために必要ですか?純粋に曖昧さ回避のためですか?もしあればあなたがnewとケースクラスをインスタンス化することができます

class Foo(val value: Int) 
object Foo { def apply(value: Int) = new Foo(value) } 

val x = new Foo(42) // 
val y = Foo(42)  // both work the same 

:あなたは自動的にapply方法あなたは普通のクラスでこれを行うことができますと同じように、コンストラクタを呼び出しコンパニオンオブジェクトを取得するケースクラスで

+4

finalは、クラスを拡張できないことを意味します。インスタンスの作成とは何の関係もありません:-)。ケースクラスは、基本的に 'マッチケース'ブロックで比較できるクラスです。 – aishwarya

答えて

6

をしたい。理論的にはコンパニオンオブジェクトのapplyメソッドを経由する必要がないために少し速くなるかもしれませんが、私はクイックベンチマークを試みてパフォーマンスに全く差がないことを知ったので、コンパイラによって最適化されているか、実際の工事と比較して差異があります。

私が与えた例のnewは意味がなく、ちょうど残っている可能性もあります。

3

正しいですか。 newは必須ではありません。彼らはただのほか、次のようにインスタンスメソッドList#::を定義することも可能です。

def ::[U >: T](x: U): List[U] = scala.::(x, this) 

(我々が持っていることに注意してください:scalaパッケージオブジェクトに定義されて

type :: = collection.immutable.:: 
val :: = collection.immutable.:: 

、最初はなぜあなたのnew scala.::(x, this)作品、および2番目の理由は私のscala.::(x, this)が機能する理由です。)

The form the library usesは、あなたのようにコンストラクタを直接呼び出します。代わりに::ケースクラスに対して生成された合成コンパニオンオブジェクトのapplyメソッドを呼び出します。これは単にコンストラクタを呼び出すだけです。おそらく、コンストラクタを呼び出すことは、より明確に、またはより効率的であると考えられましたか? (コンパイラはapplyへの呼び出しをインライン化しない場合は、JVMがするので、効率性の向上は、しかし、何に近くなければなりません。)私は最もコンパクトな形式とします

def ::[U >: T](x: U) = ::(x, this) 

は(いくつかの奇抜と誤解することができいずれにしても、::というクラスと::というメソッドの区別がぼやけてしまいます。これは、Odersky教授が読者の理解を最大限にするために別にしておくことです。

これが役に立ちます。

関連する問題