我的游戏
class Enemy
我可以用
更改谁的AI /功能trait Moving
trait VerticalMover extends Moving
trait RandomMover extends Moving
等等。现在我需要根据特征获取预加载的东西。我想要做的是有一个Map接受所有延伸移动的特征,然后将一些EnemyContainer作为预先加载特征相关内容的值。
但是我如何定义这样的Map以及如何格式化我的.get()以通过某个Enemy的实例来获取容器。类似的东西:
val myEnemy = new Enemy with RandomMover
val myDetails:EnemyContainer = enemyDetailsStore.get(myEnemy.getClass)
答案 0 :(得分:11)
也许你可以包装Map [Manifest,Any],确保值对应于清单键。
可能的草图。首先是一个小帮手
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])
}
}
然后是包装器本身(不是地图)
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) : _*))
}
你可以这样做
import Typed._
val repository = TypedMap("foo", 12, "bar".typedAs[Any])
repository:TypedMap = Map(java.lang.String - > foo,Int - > 12,Any - > 巴)
使用
检索元素repository[String] // returns "foo"
repository.get[Any] // returns Some("bar")
我认为私有构造函数应该确保_ asInstanceOf
是安全的。 inner
可能会公开,因为它是不可变的。这样,Map
的丰富界面将可用,但遗憾的是,不会创建另一个TypedMap
。
答案 1 :(得分:5)
好吧,我假设您的敌人详情商店的类型为Map[Class[_ <: Moving], EnemyDetails]
。我怀疑像:
//gives a Map[Class[_ <: Moving], EnemyDetails] for all matching keys
enemyDetailsStore.filterKeys(_ isInstance myEnemy)
或者:
//Iterable[EnemyDetails]
enemyDetailsStore collect { case (c, d) if c isInstance myEnemy => d }
甚至只是:
//Option[EnemyDetails]
enemyDetailsStore collectFirst { case (c, d) if c isInstance myEnemy => d }
会为你做的。这段代码唯一的“问题”是它是O(N),因为它需要遍历地图,而不是简单的查找,即O(1)或O(log N)