How to create an object attribute from polymorphic type in scala -
i trying create object store instances object created , avoid re-load. tried create mutable map on object store it, compilation error.
this code:
class bar class foobar extends bar object foo { val loaded = scala.collection.mutable.map[string, bar]() def apply[t <: bar](implicit m: manifest[t]): t = { val classname = m.tostring() if (loaded.contains(classname)) { return loaded(classname) } val instance = m.runtimeclass.newinstance().asinstanceof[t] loaded(classname) = instance instance } }
but when try compile error:
error: type mismatch; found : bar required: t return loaded(classname)
there way create map dynamically , pass t? or solve differently?
your problem in returning loaded(classname)
of type bar
, not t
required function type signature. unfortunately, cannot encode such dependence between types of map keys , values, @ least not standard map collection. have perform explicit cast. here working example:
import scala.reflect.classtag class bar class foobar extends bar object test { val classmap = scala.collection.mutable.map[class[_], bar]() def getinstance[t <: bar : classtag]: t = { val ct = implicitly[classtag[t]] classmap ct.runtimeclass match { case some(bar) => bar.asinstanceof[t] case none => val instance = ct.runtimeclass.newinstance().asinstanceof[t] classmap(ct.runtimeclass) = instance instance } } } object main { def main(args: array[string]) { println(test.getinstance[foobar]) println(test.getinstance[bar]) println(test.getinstance[foobar]) } }
note i'm using classtag
instead of manifest
because manifest
deprecated. modern equivalent typetag
, task classtag
more enough.
update
here variants of code suggested @0__. first:
import scala.reflect.classtag class bar class foobar extends bar object test { val classmap = scala.collection.mutable.map[class[_], bar]() def getinstance[t <: bar : classtag]: t = { val ct = implicitly[classtag[t]] classmap ct.runtimeclass match { case some(bar: t) => bar case none => val instance = ct.runtimeclass.newinstance().asinstanceof[t] classmap(ct.runtimeclass) = instance instance } } } object main { def main(args: array[string]) { println(test.getinstance[foobar]) println(test.getinstance[bar]) println(test.getinstance[foobar]) } }
and second, best 1 imo:
import scala.reflect.classtag class bar class foobar extends bar object test { val classmap = scala.collection.mutable.map[class[_], bar]() def getinstance[t <: bar : classtag]: t = { val ct = implicitly[classtag[t]] classmap.getorelseupdate(ct.runtimeclass, ct.runtimeclass.newinstance().asinstanceof[bar]).asinstanceof[t] } } object main { def main(args: array[string]) { println(test.getinstance[foobar]) println(test.getinstance[bar]) println(test.getinstance[foobar]) } }
Comments
Post a Comment