通过 Scala 或 java 中的继承扩展一组命名值

Extending a set of named values via inheritance in scala or java

我知道有人问了很多关于枚举和特征的问题,但是我想从我必须讨论最优雅的方式的要求开始,我意识到枚举和特征都不可能完成这项工作。

首先考虑构成我的要求的这个简单示例

trait Sound{
  def makeSound(animal: Animal.value): String
}

关键部分 是我希望程序员能够通过输入 "Animal." 来检查允许的动物列表。但是,该列表应该能够通过新的实现进行扩展。由于这些原因,以下尝试均失败。

特征实现

如果我将我的 makeSound 参数定义为 Animal,这是可扩展的,但是使用该函数的程序员看不到哪些动物可用。

trait Animal
case object Dog extends Animal
case object Cat extends Animal

枚举实现

这适用于要列出的可能值,但如果我想扩展它,那么我需要创建一个新对象,使用新名称,这样就达不到目的了。

object Animal extends Enumeration {
  type Animal = Value
  val Dog, Cat = Value
}

问题 如前所述,我意识到上面的两个例子都不符合要求。更多的是将它们从我记下的答案中排除。实际问题是,你将如何做到这一点?部分选项:

谢谢!

The crucial part is that I want programmers to be able to check the list of allowed animals by typing in "Animal.".

您可以在不修改 Animal 的情况下使用隐含函数来完成此操作:

trait Animal
object Animal

// somewhere visible from your code
implicit class CatAnimal(singleton: Animal.type) {
  case object Cat extends Animal
}

// in your code
Animal.Cat // uses the implicit class

问题出在 "somewhere visible from your code" 部分。它可以被导入,但是开发人员需要知道它存在才能导入它,这可能会破坏目的。它可以添加到现有位置,但为什么不首先将其添加到 Animal

一个简单的解决方案是为名称设置一个通用前缀:

trait Animal
case object AnimalDog extends Animal
case object AnimalCat extends Animal

然后自动完成将正常工作,只需键入 Animal 而无需 .