gpt4 book ai didi

class - Scala:从子类引用伴随对象

转载 作者:行者123 更新时间:2023-11-30 23:54:56 26 4
gpt4 key购买 nike

我正在考虑以下 Scala 类布局。我有一个代表 Item 的基本特征——一个应该是不可变对象(immutable对象)的接口(interface),我们可以通过调用 equip 之类的方法来查询名称、重量和做一些特定于对象的事情:

trait Item {
def name: String
def weight: Int
def equip // ... more abstract methods
}

我可以创建 Item 实现,手动创建案例类,但我想要某种基于“字典”的项目——即静态映射保存从类型 ID 到值的映射, nameweight 方法只查询具有存储类型 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
}

到目前为止,还不错。我可以使用 Weapon(1) 来引用“短剑”的项目对象。然而,相同的基本原则适用于任何其他项目类型,例如 Armor,它使用完全相同的 nameweight 实现,但完全不同的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) 以及如何向编译器解释 child 的伴随对象必须包含这些词典?是否有更好、更像 Scala 的方法来解决此类问题?

最佳答案

您可以使用案例类的实例,而不是在 map 中查找项目的名称和权重。事实上,您可能希望采用这种方法有一些充分的理由:

  1. Avoid Complexity: It's simple enough, you might not have needed to post this question about how inheritance works with companion classes.
  2. Avoid Repetition: Using case classes, you would only have to define your items once.
  3. Avoid Errors: Using synthetic keys, would require you to use the correct key in both the name and weight dictionaries. See item 2.
  4. Write Idiomatic Code: Scala is both object-oriented and functional. In this case, orient yourself around the Item.
  5. Avoid Overhead: Get all the item's properties with a single lookup.

这是 Item 扮演主角的不同视角:

package object items {
val weapons = Weapon("halbred", 25) :: Weapon("pike", 35) :: Nil
val armor = Armor("plate", 65) :: Armor("chainmail", 40) :: Nil
val dictionary = (weapons ::: armor) map(item => item.name -> item) toMap
}

请注意,名称和权重打包在实例中,而不是打包为映射中的值。并且没有要管理的索引。但是,如果您出于某种原因需要索引,您可以轻松地使用该项目在设备列表中的位置或向 Item 特征添加一个属性。

并且,您可以像这样使用它:

> items dictionary("halbred")        // Weapon(halbred, 25)
> items dictionary("plate") weight // 65

最后一点,Scala 词中的 final 关键字有点不合时宜。当您在 Scala 中定义一个 val 时,它已经是不可变的:Why are `private val` and `private final val` different?

关于class - Scala:从子类引用伴随对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13655188/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com