4

这可以做到吗?

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

当使用给定的构造函数构造时,C 自动为 C[Boolean]。此版本无法编译,但感觉它应该以某种方式可行,尤其是在以下似乎可行的情况下:

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

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

4

2 回答 2

3

出什么问题了

object C{
  def apply() = C(true)
}

这样您就可以使用伴随对象?在 Java 中,这将是,C$.apply()不是吗?

于 2014-02-20T16:15:03.687 回答
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 互操作也不是那么糟糕。您可以执行以下操作:

// 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$.

于 2014-02-20T16:34:39.850 回答