Question

Can this be done?

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

When constructed with given constructor, C is automatically a C[Boolean]. This version does not compile but it feels like it should be doable somehow, especially as the following seems to work:

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

I want some Java interoperability, so I try to avoid default values. I think that I can achieve this by using factory methods in a companion object, but can it be done directly? As C is a case class, factory methods are a bit messy IMHO.

Was it helpful?

Solution 2

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

OTHER TIPS

What is wrong with

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

such that you use the companion object? In Java, this would be, C$.apply() no?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top