I'm thinking of a following Scala class layout. I have a basic trait that represents an Item - an interface of what ought to be an immutable object that we can query for name, weight and do some object-specific stuff by invoking methods like equip
:
trait Item {
def name: String
def weight: Int
def equip // ... more abstract methods
}
I can create Item
implementations, creating case classes by hand, but I'd like to have some sort of "dictionary"-based items - i.e. a static map holds mapping from type ID to values, name
and weight
methods just query the dictionary with a stored type ID:
object Weapon {
final val NameDict = Map(1 -> "short sword", 2 -> "long sword")
final val WeightDict = Map(1 -> 15, 2 -> 30)
}
case class Weapon(typ: Int) extends Item {
import Weapon._
def name = NameDict(typ)
def weight = WeightDict(typ)
def equip = ... // implementation for weapon
}
So far, so good. I can use Weapon(1)
to reference an item object for "short sword". However, the same basic principle applies to any other item types, such as Armor
, which uses exactly the same name
and weight
implementation, but completely different equip
and other abstract methods implementation, for example:
object Armor {
final val NameDict = Map(3 -> "bronze armor", 4 -> "iron armor")
final val WeightDict = Map(3 -> 100, 4 -> 200)
}
case class Armor(typ: Int) extends Item {
import Armor._
def name = NameDict(typ)
def weight = WeightDict(typ)
def equip = ... // implementation for armor
}
Looks pretty similar to Weapon
, isn't it? I'd like to factor out the common pattern (i.e. implementation of lookups in companion object dictionaries and common typ
value) in something like that:
abstract class DictionaryItem(typ: Int) extends Item {
def name = ???.NameDict(typ)
def weight = ???.WeightDict(typ)
}
object Weapon {
final val NameDict = Map(1 -> "sword", 2 -> "bow")
final val WeightDict = Map(1 -> 15, 2 -> 30)
}
case class Weapon(typ: Int) extends DictionaryItem(typ) {
def equip = ... // implementation for weapon
}
But how do I reference a children's companion object (like Weapon.NameDict
) from parent class - i.e. what should I use instead of ???.NameDict(typ)
and how do I explain to the compiler that children's companion object must include these dictionaries? Is there a better, more Scala-esque approach to such a problem?