2016-03-10 38 views
0

我想在Scala中构建类似于类注册表的东西,我可以从一个键中获取一个类对象。 关键是我想确保我的类继承一个共同的特征。Scala中有界类型的地图

类似的东西:

trait GenericTrait{ 
    def doSomethingCool() 
} 
trait AbstractRegistry { 
    def registry[T <: GenericTrait]:Map[String, Class[T]] 
} 

class Object1 extends GenericTrait{ 
    override def doSomethingCool()= println("hello") 
} 

class Object2 extends GenericTrait{ 
    override def doSomethingCool()=println("hi") 
} 

object MyClassRegistry extends AbstractRegistry { 
    override def registry[T <: GenericTrait]:Map[String, Class[T]]=Map(
     "obj1" -> classOf[Object1], 
     "obj2" -> classOf[Object2] 
) 
} 

但它看起来像我错过了一些东西,因为它不会编译... 任何想法?

回答

3

A中的类[A]为invariant。这基本上意味着如果您有Map[String, Class[GenericTrait]],则无法放入类型为Class [Object1]或Class [Object2]的映射值,因为它们不是Class [GenericTrait]的子类型。

您必须声明映射值的上限类型绑定_ <: GenericTrait,以便它们变成“Class [T]类型,其中T是GenericTrait的子类”。您也可以将T AbstractRegistry的类型参数,而不是方法

trait GenericTrait { 
    def doSomethingCool() 
} 

trait AbstractRegistry[T <: GenericTrait] { 
    def registry: Map[String, Class[_ <: T]] 
} 

class Object1 extends GenericTrait { 
    override def doSomethingCool() = println("hello") 
} 

class Object2 extends GenericTrait { 
    override def doSomethingCool() = println("hi") 
} 

object MyClassRegistry extends AbstractRegistry[GenericTrait] { 
    override def registry: Map[String, Class[_ <: GenericTrait]] = Map(
    "obj1" -> classOf[Object1], 
    "obj2" -> classOf[Object2] 
) 
} 

当你评论,你并不真正需要的AbstractRegistry类型的参数,如果你并不需要能够限制你的注册表子类GenericTrait后代的子树。

trait AbstractRegistry { 
     def registry: Map[String, Class[_ <: GenericTrait]] 
    } 
+1

工程就像一个魅力。谢谢 ! 编辑:'高清注册表:地图[字符串,类[_ <:GenericTrait]]似乎工作得很好,甚至更简单。 –

+0

是的,我将AbstractRegistry类型参数留在您的示例中。这不是真的需要,你只能用它来限制注册表到GenericTrait后代的某个子族。补充说,回答:) –

+0

“他们不是类[GenericTrait]”的子类Nitpick:子类型,而不是子类。 –