I suspect factory methods in the companion object are the best you can do (as wheaties
has suggested). We can make it compile, but at the expense of sillyness down the line. For example:
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
The basic problem is that type parameters are specified at the class level, not the constructor level, so all constructors have to use the same type parameters. On the other hand, methods can take type parameters, so factory methods are no problem. Also, Java Interop for factory methods isn't all that bad. You could do something like:
// 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();
}
The scala compiler creates static methods to simplify Java interop, so you don't usually need to mess around with C$
.