Forse potresti avvolgere una mappa [Manifest, Any] assicurandoti che i valori corrispondano alle chiavi manifest.
Possibile schizzo di quello. Prima un piccolo aiutante
class Typed[A](value: A)(implicit val key: Manifest[A]) {
def toPair: (Manifest[_], Any) = (key, value)
}
object Typed {
implicit def toTyped[A: Manifest](a: A) = new Typed(a)
implicit def toTypable[A](a: A) = new {
def typedAs[T >: A : Manifest] = new Typed[T](a)(manifest[T])
}
}
quindi l'involucro in sé (che non è una mappa)
class TypedMap private(val inner: Map[Manifest[_], Any]) {
def +[A](t: Typed[A]) = new TypedMap(inner + t.toPair)
def +[A : Manifest](a: A) = new TypedMap(inner + (manifest[A] -> a))
def -[A : Manifest]() = new TypedMap(inner - manifest[A])
def apply[A : Manifest]: A = inner(manifest[A]).asInstanceOf[A]
def get[A : Manifest]: Option[A] = inner.get(manifest[A]).map(_.asInstanceOf[A])
override def toString = inner.toString
override def equals(other: Any) = other match {
case that: TypedMap => this.inner == that.inner
case _ => false
}
override def hashCode = inner.hashCode
}
object TypedMap {
val empty = new TypedMap(Map())
def apply(items: Typed[_]*) = new TypedMap(Map(items.map(_.toPair) : _*))
}
Con questo si può fare
import Typed._
val repository = TypedMap("foo", 12, "bar".typedAs[Any])
repository: TypedMap = Map (java .lang.String -> foo, Int -> 12, Any -> bar)
si recupera gli elementi con
repository[String] // returns "foo"
repository.get[Any] // returns Some("bar")
Credo che il costruttore privato deve garantire che il _ asInstanceOf
è sicuro. inner
può essere lasciato pubblico, in quanto è immutabile. In questo modo, la ricca interfaccia di Map
sarà disponibile, ma sfortunatamente, non per creare un altro TypedMap
.
fonte
2011-09-07 16:52:02
Vuoi dire che 'enemyDetailsStore' restituisce una cosa se' MyEnemy' estende 'VerticalMover', e un'altra cosa se estende' RandomMover'? Cosa succede se estende entrambi? –
Sì, questo è quello che intendevo. Ma sto iniziando a chiedermi per la sanità mentale di tutta la mia idea. Forse dovrei avere qualche stringa chiave incorporata nei tratti e usarla come chiave. Quindi, con la linearizzazione dei tratti, l'ultimo tratto dominante avrebbe impostato l'EnemyContainer in altre parole le trame utilizzate per visualizzare il nemico. – vertti
La maggior parte delle volte, il punto di un tratto/interfaccia è dire "So come fare * X *", pur consentendo diverse implementazioni di X. In assenza di altri dettagli, avrei pensato che il design più naturale sarebbe avere il tratto 'Moving' ha una sorta di metodo' getMovingStrategy' o 'move' su di esso direttamente, che è possibile implementare di conseguenza nei sottotit del motore verticale e casuale. –