Я думаю о следующем макете класса Scala. У меня есть базовая черта, которая представляет собой Item - интерфейс того, что должно быть неизменяемым объектом, который мы можем запрашивать для имени, веса и делать некоторые специфичные для объекта вещи, вызывая такие методы, как equip
:
trait Item {
def name: String
def weight: Int
def equip // ... more abstract methods
}
Я могу создавать Item
реализации, создавая классы case вручную, но я бы хотел иметь какие-то элементы на основе "словаря", то есть статическая карта содержит сопоставление от идентификатора типа к значениям, методы name
и weight
просто запрашивают словарь с идентификатор сохраненного типа:
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
}
Все идет нормально. Я могу использовать Weapon(1)
для ссылки на объект предмета для "короткого меча". Однако тот же базовый принцип применяется к любым другим типам элементов, таким как Armor
, который использует точно такую же реализацию name
и weight
, но совершенно другую реализацию equip
и других абстрактных методов, например:
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
}
Выглядит очень похоже на Weapon
, не так ли? Я хотел бы выделить общий шаблон (то есть реализацию поиска в словарях сопутствующих объектов и общее значение typ
) примерно таким:
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
}
Но как мне сослаться на детский объект-компаньон (например, Weapon.NameDict
) из родительского класса - т.е. что мне следует использовать вместо ???.NameDict(typ)
и как мне объяснить компилятору, что детский объект-компаньон должен включать эти словари? Есть ли лучший, более похожий на Scala подход к такой проблеме?