2014-10-25 7 views
17

Wie diese Zusammenstellung Fehler beheben:Wie loswerden: Klassentyp erforderlich, aber T gefunden

trait Container { 
    def getInts() : Seq[Int] 
    def getStrings() : Seq[String] 

    def put[T](t: T) 
    def get[T] : Seq[T] 
} 

class MutableContainer extends Container { 
    val entities = new mutable.HashMap[Class[_], mutable.Set[Any]]() with mutable.MultiMap[Class[_], Any] 

    override def getStrings(): Seq[String] = entities.get(classOf[String]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[String]] //strings 
    override def getInts(): Seq[Int] = entities.get(classOf[Int]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[Int]] 

    override def get[T]: Seq[T] = entities.get(classOf[T]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[T]] 
    override def put[T](t: T): Unit = entities.addBinding(t.getClass, t) 
} 

Hier ist der Fehler:

[error] Container.scala:23: class type required but T found 
[error]  override def get[T]: Seq[T] = entities.get(classOf[T]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[T]] 

Antwort

24

T ist kein Klassentyp, sondern ein Typ Parameter. Fordern Sie ein ClassTag:

import scala.reflect._ 

override def get[T](implicit ct: ClassTag[T]): Seq[T] = 
    entities.get(ct.runtimeClass) 
      .map(_.toSeq) 
      .getOrElse(Seq.empty) 
      .asInstanceOf[Seq[T]] 

Aber das bringt ein anderes Problem; Das ist kein Override!

So haben Sie die Basisklasse ändern get zu erklären, wie folgt:

def get[T: ClassTag]: Seq[T] 
+0

keine andere Möglichkeit, die Compiler ein Typparameter ist notwendigerweise ein Klassentyp zu sagen, ? [Ich probierte sogar einen Typparameter T <: SomeClass in meinem Fall] (http://stackoverflow.com/questions/32797731/passing-a-type-parameter-for-instantiation), und der Typ gebunden überzeugte nicht Compiler das ist ein Typ :( – matanster

1

Eine Lösung ohne Reflexion

trait Container { 
    def getInts() : Seq[Int] 
    def getStrings() : Seq[String] 
    def put[T](clazz: Class[T],t :T) 
    def get[T](clazz: Class[T]) : Seq[T] 
} 

class MutableContainer extends Container { 
    val entities = new mutable.HashMap[Class[_], mutable.Set[Any]]() with mutable.MultiMap[Class[_],Any] 
    override def getStrings(): Seq[String] = entities.get(classOf[String]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[String]] //strings 
    override def getInts(): Seq[Int] = entities.get(classOf[Int]).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[Int]] 
    override def get[T](clazz: Class[T]): Seq[T] = entities.get(clazz).map(_.toSeq).getOrElse(Seq.empty).asInstanceOf[Seq[T]] 
    override def put[T](clazz: Class[T],t :T): Unit = entities.addBinding(clazz, t) 
} 
+0

Das ist eine weniger fließende API. Caller-Code will nicht mit diesem Zeug umgehen. –

Verwandte Themen