単純な答えはいいえです。型システムは、クラスにデフォルトのコンストラクタがあるかどうかを伝えることはできません。引数のない大文字小文字のクラスは非推奨であるため、通常、大文字と小文字のクラスにはデフォルトのコンストラクタがありません。デフォルトコンストラクタのコンセプトは、不変オブジェクトではそれほど有用ではありません。 AFAIKでは、原理的には存在しないべき理由はありません(スカラは、型が特定の名前のメソッドを持たなければならない構造型をサポートしています)が、言語の変更が必要です。あなたはリフレクションでランタイムにチェックすることができますが、それはあなたが望むものではありません。
ただし、typeクラスパターンを使用すると、デフォルト値を有効範囲にすることができます。これは概念的には、OPで示唆されているような追加のデフォルトの引数を追加することに非常によく似ていますが、implicitsを使用してそれらを隠すことです。これはコレクションライブラリで頻繁に使用されています。この場合、scalaz.Zero
を使ったmissingfaktorの答えは特別なケースですが、バニラのScalaや、ある種のゼロではない任意のデフォルトでは、やりにくいです。
case class Default[T](default: T)
case class Foo(value: String)
case class Bar(value: Int)
implicit val fooDefault = Default(Foo("I'm a default Foo")) // note 1
今の使用例を見てみましょう:
def firstItem[T](lst: List[T]) (implicit ev: Default[T]) = // note 2
if (lst.isEmpty) ev.default else lst.head
val fooList = List(Foo("cogito"), Foo("ergo"), Foo("sum"))
val emptyFooList = List[Foo]()
val barList = List(Bar(101), Bar(102))
val emptyBarList = List[Bar]()
firstItem(fooList) // Foo("cogito")
firstItem(emptyFooList) // Foo("I'm a default Foo")
firstItem(barList) // ** error: missing implicit **
だから私たちは、これがList[Foo]
でコンパイルしますが、暗黙Default[Bar]
(注3)が存在しないので、List[Bar]
が受け入れられないことがわかります。
注1:この暗黙のはobject Foo
に定義することができ - あなたが他の場所でクラスをインポートする場合、それがスコープ内にあることを確認しますと思われます。しかし、必ずしもそうである必要はありません。任意のクラスの類似implicitsを定義することもできます(Int
、String
、何でも試してみてください)。
注2:これは、def firstItem[T: Default](lst: List[T]) =
...と同じです。ここでは、ev
をimplicitly[Default[T]]
と召喚します。好きなのを選びな。
注3:私たちは、それは単に1を供給することによって動作させることができます。
firstItem(barList)(Default(Bar(42))) // Bar(101)
firstItem(emptyBarList)(Default(Bar(42))) // Bar(42)
注: 'F'メソッド、関数ではなく。関数は '=>'(基本的には 'FunctionN'特性の1つを匿名で拡張し、' apply'をオーバーライドするための文法的砂糖です)で作成され、 'def'メソッドを定義します。 –
ご同意いただき、ありがとうございます。 – folone