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

时间:2018-02-22 09:46:23

标签: scala enums traits

我知道很多关于枚举的问题和特征已经被问到,但是我想从我要讨论最优雅的方式开始,我意识到无论是枚举还是特质都不会起作用。

首先考虑形成我的要求的这个简单例子

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
}

问题 如上所述,我意识到上述两个例子都不符合要求。更多的是将它们从我记下来的答案中排除。实际的问题是,你会怎么做?一些选择:

  • 基于文件的配置
  • 让开发人员在实施新功能时调整Animal的源代码。
  • 还有什么?

谢谢!

1 个答案:

答案 0 :(得分:3)

  

关键部分是我希望程序员能够通过输入“Animal”来检查允许的动物列表。

您可以在不使用implicits修改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

问题在于“代码可见的某个地方”部分。它可以导入,但是开发人员需要知道它存在才能导入它,这可能会破坏目的。它可以添加到现有的locaction中,但是为什么不首先将它添加到Animal

一个简单的解决方案是为名称添加一个公共前缀:

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

然后自动填充功能正常,只需在Animal处输入.即可。