Reputation: 5093
Is it possible in Scala to define the singletons for a class with a generic parameter? Yes its the plural, because there must be a singleton for each instance of the generic parameter. This is nonsense in the most general case, I believe, but if the generic parameter is a subtype of something specific, I wonder whether it may work.
As an example consider as the specific supertype of all generic parameters to be this abstract class.
abstract class BaseType[T<:BaseType] {
val omega:T;
}
The idea is that each implementation has a special value, and this is omega. Now I want a class which has subtypes of BaseType
as a generic parameter:
class Thing[T<:BaseType[T]](val v:T, foo:Int);
Because each T
has the specific value omega
, I would like to have singletons for Thing
containing omega
and, say, foo=0
. I cannot even do
object Thing {
def OmegaInstance[T<:BaseType[T]] = new Thing(/*what gos here?*/, 0);
}
but even if I could, the OmegaInstance would be new for each call, which I don't want.
Any chance to get this working?
Upvotes: 1
Views: 222
Reputation: 22374
If your input type parameter is not erased you can implement same old lightweight pattern, but with TypeTag
as a key:
import scala.reflect.runtime.universe._
import scala.collection.concurrent._
object Things {
class Thing[T] private[Things]() { //private constructor, class itself is still accessable
//...
}
private val map = TrieMap[TypeTag[_], Thing[_]]()
def Thing[T: TypeTag] =
map.getOrElseUpdate(typeTag[T], new Thing[T]).asInstanceOf[Thing[T]] //`asInstanceOf` is safe here
}
Usage examples:
import Things._
scala> Thing[Int]
res2: Things.Thing[Int] = Things$Thing@4472abe8 //new object
scala> Thing[Int]
res3: Things.Thing[Int] = Things$Thing@4472abe8 //same object
scala> Thing[Int]
res4: Things.Thing[Int] = Things$Thing@4472abe8 //same object
scala> Thing[String]
res5: Things.Thing[String] = Things$Thing@4745c8d2 //new object
scala> Thing[String]
res6: Things.Thing[String] = Things$Thing@4745c8d2 //same object
You can instantiate any thing you want with any parameter here. The usage looks almost like just having generic-parameterized object
(one singleton for every generic).
Upvotes: 0