修复了替代构造函数中的类型参数

时间:2014-02-20 15:49:01

标签: scala constructor parameterized-class

可以这样做吗?

final case class C[A] (v: A) {
  def this() = this(true)
}

当使用给定的构造函数构造时,C自动为C [Boolean]。这个版本没有编译,但感觉它应该以某种方式可行,特别是因为以下似乎工作:

final case class C[A] (v: A = true)

我想要一些Java互操作性,所以我尽量避免使用默认值。我认为我可以通过在伴随对象中使用工厂方法来实现这一点,但它可以直接完成吗?由于C是一个案例类,工厂方法有点乱,恕我直言。

2 个答案:

答案 0 :(得分:3)

有什么问题
object C{
  def apply() = C(true)
}

这样你就可以使用伴侣对象?在Java中,这可能是C$.apply()没有?

答案 1 :(得分:2)

我怀疑伴侣对象中的工厂方法是你能做的最好的(正如wheaties建议的那样)。我们可以编译它,但是以牺牲愚蠢为代价。例如:

final case class C[A] (v: A) {
  def this() = this("Hello".asInstanceOf[A]) // Compiles, thanks to type erasure
}

val c = new C[Int]() // Still compiles, despite the fact that "Hello" is not an Int
println(c) // C(Hello)
c.v + 1 // Compiles, but throws a ClassCastException at run-time

基本问题是类参数是在类级而不是构造函数级指定的,因此所有构造函数都必须使用相同的类型参数。另一方面,方法可以采用类型参数,因此工厂方法没有问题。此外,工厂方法的Java Interop并不是那么糟糕。你可以这样做:

// C.scala
final case class C[A] (v: A) 
object C {
    def apply(): C[Boolean] = C(true)
}

// Test.java
public class Test {
    public C c = C.apply();
}

scala编译器创建静态方法来简化Java互操作,因此通常不需要使用C$