您可以在empty
方法直接指定类型,而不必添加额外的设置括号/括号和类型注释:
class Bar[A](set: Set[Foo[A]] = Set.empty[Foo[A]])
至于为什么类型推断失败,看到这些问题:
更新:
我很抱歉,我匆忙的回答是路要走。上面的帖子中的问题与这个问题并没有真正的关系。 @TravisBrown在他上面的评论中提到了一个很好的观点。这似乎在第一工作:
class Bar[A](set: Set[A] = Set.empty)
但如果你真的尝试调用它无法在使用现场的构造:
new Bar[Int]
// <console>:9: error: type mismatch;
// found : scala.collection.immutable.Set[Nothing]
// required: Set[Int]
// Note: Nothing <: Int, but trait Set is invariant in type A.
// You may wish to investigate a wildcard type such as `_ <: Int`. (SLS 3.2.10)
// Error occurred in an application involving default arguments.
// new Bar[Int]
这表明编译器不强制默认参数对所有A
有效,仅适用于某些A
。他们大概做了这个选择,所以你可以做这样的事情:
scala> case class MyClass[T](set: Set[T] = Set(0))
defined class MyClass
scala> MyClass() // defaults to MyClass[Int]
res0: MyClass[Int] = MyClass(Set(0))
scala> MyClass(Set('x)) // but I can still use other types manually
res1: MyClass[Symbol] = MyClass(Set('x))
然而,任何形式的与参数化类型嵌套无法键入构造检查在声明的网站:
class Bar[A](set: Set[Option[A]] = Set.empty)
// <console>:7: error: polymorphic expression cannot be instantiated to expected type;
// found : [A]scala.collection.immutable.Set[A]
// required: Set[Option[?]]
// class Bar[A](set: Set[Option[A]] = Set.empty)
的因为编译器选择Nothing
作为共
class Bar[ A ](set: List[Foo[A]] = List.empty) // OK
class Bar[ A ](set: Map[Int,Foo[A]] = Map.empty) // OK (unless you use it)
class Bar[ A ](set: Map[Foo[A],Int] = Map.empty) // BAD
// <console>:8: error: polymorphic expression cannot be instantiated to expected type;
// found : [A, B]scala.collection.immutable.Map[A,B]
// required: Map[Foo[?],Int]
// class Bar[ A ](set: Map[Foo[A],Int] = Map.empty) // BAD
// ^
这些工作:推论不会失败,如果类型参数是在协变位置变体类型默认。这适用于List
,但上面的第二个示例在您实际尝试调用它时不起作用。
大部分这种奇怪的原因可能是Scala处理默认参数的方式。编译器会自动为伴随对象添加一个额外的方法,然后无论您何时离开参数,编译器都会自动将方法调用添加到伴随对象中的新方法以生成缺少的参数。它看起来像将缺省参数抽象为一个方法会破坏类型推断中的一些东西,这些东西可以用于正常的赋值。
我认为这些发现大部分都相当混乱。我从中获得的是,实际测试默认参数非常重要,以确保在尝试使用它们时不会破坏类型正确性!
不是答案,但需要注意三点:为了避免与'found:[A] scala.collection中的(不同)'A'混淆,您可能想要指定类型参数而不是'A'。 immutable.Set [A]'message;关于'Set'和你的'Hallo'的重要事实是它们是不变的(而不是'List');你最后一行的编译可能不会做你想要的。 –
虽然'class Bar [A](hallo:Hallo [A] = Hallo.apply)'如果你改变它使用'Hallo.apply()'它可以正常工作。你应该能够离开这个parens,所以它在这里一定会变得非常困惑。它认为你正在传递部分应用的函数'Hallo.apply',而不是调用没有参数的'apply'。 (错误消息说它发现类型'[A]()Hallo [A]'。) – DaoWen