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?