I have a case class, taking a Seq[T] as parameter:
case class MyClass(value: Seq[T])
I now want to be able to write
MyClass(t1,t2,t3)
So I defined
object MyClass {
def apply(value: T*) = new MyClass(value.toSeq)
}
It doesn't work, because the case class defines
object MyClass {
def apply(value: Seq[T])
}
and Seq[T] and T* have the same type after erasure, so I can't overload them.
But I'd like to allow both access ways. Both ways should be allowed:
MyClass(t1,t2,t3)
MyClass(some_seq_of_T)
Since Seq[T] and T* are almost the same type (at least after erasure; and inside of the function having the parameter T* becomes Seq[T]), I think there should be a way to allow both ways of calling it.
Is there?
You could cheat a little bit and define your companion like this:
case class MyClass[T](value: Seq[T])
object MyClass {
def apply[T](first: T, theRest: T*) = new MyClass(first :: theRest.toList)
def apply[T]() = new MyClass[T](Nil)
}
The first apply
handles the MyClass(1,2,3)
as long as there is at least one argument.
The scond apply
handles the 0-argument case. They don't conflict with the regular constructor.
This way you can write MyClass(Seq(1,2,3))
, MyClass(1,2,3)
, and MyClass()
. Just note that for the empty one you'll have to tell it what type to return, or else it will assume a MyClass[Nothing]
Here is solution without case classes:
scala> class A[T] (ts: Seq[T]) { def this(ts: T*)(implicit m: Manifest[T]) = this(ts) }
defined class A
scala> new A(1)
res0: A[Int] = A@2ce62a39
scala> new A(Seq(1))
res1: A[Seq[Int]] = A@68634baf
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With