我正在使用" case类而不是Enumeration"模式,并希望得到每个"枚举"的所有值的列表以及一些方法。因此,我决定不仅从密封的抽象类派生我的case类,而是从名为Lookup的超类派生所有密封的抽象类,并定义一个LookupTrait,从中派生抽象类'伴侣物体。
abstract class Lookup {
val name: String
override def toString = name
}
trait LookupTrait[T<:Lookup] {
val all: Map[String, T]
val default: T
def withName(name: String): T =
if(all.contains(name)) all(name)
else default
}
示例查找如下所示:
sealed case class StudyGoal(override val name: String) extends Lookup
object StudyGoal extends LookupTrait[StudyGoal] {
override val all = Map(
"present new evaluation method" -> StudyGoal("present new evaluation method"),
"evaluate existing product" -> StudyGoal("evaluate existing product"),
"develop new theoretical model" -> StudyGoal("develop new theoretical model"),
"unknown" -> StudyGoal("unknown")
)
override val default = StudyGoal("unknown")
}
我更愿意在每个查找的伴随对象中定义一个字符串列表,并让trait实例化case类。但是当我在Scala中发现三种不同的反射方式时 - 使用Manifest,TypeTag,并获得类in the documentation所描述的类的构造函数,所有这些方法似乎都需要有一个类的实例存在,我无法让它们在参数化的LookupTrait特性中工作。
我希望有类似的东西:
abstract class Lookup {
val name: String
override def toString = name
}
trait LookupTrait[T<:Lookup] {
val allNames: List[String]
val default: T = //Instantiate a T using the string "unknown".
//It is OK that this string will be the same for all Lookups.
val all: Map[String, T] = allNames.map(
n => n -> //instantiate a T here, using n as the parameter
) += default
def withName(name: String): T =
if(all.contains(name)) all(name)
else default
}
sealed case class StudyGoal(override val name: String) extends Lookup
object StudyGoal extends LookupTrait[StudyGoal] {
override val allNames = List(
"present new evaluation method"),
"evaluate existing product",
"develop new theoretical model"
)
}
答案 0 :(得分:1)
我有一个关闭的lib,只需要你定义case对象而不是只使用字符串:https://github.com/lloydmeta/enumeratum
它由一个宏驱动,通过一点工作/修改,可能会产生你想要的(在编译时,基于字符串定义实例)
答案 1 :(得分:0)
因此,根据您对“我想要的内容”部分的评论,看起来您希望进一步参数化“实例化T”。您可以向LookupTrait
添加一个抽象方法,该子类需要实现;它可能有一个签名,如:
def instantiateElement(name: String): T
但是,我对你要做的事情感到有些困惑。 Scala Enumerations旨在像Java枚举一样使用 - 用于处理固定的,有限的选择集。您通常将每个元素绑定到PascalCase名称,以便稍后可以将未知值与这组名称进行模式匹配。您的案例看起来不像固定的有限集,更像是动态的开集。也许你完全不需要这些;也许普通Set[String]
就足够了。