在Java中,我做了很多数据集成工作。一直出现的一件事是在多个系统之间映射数据。所以我经常做这样的事情
public enum DataField{
Field1("xmlField", "dbField", "system1Field";
private String xml;
private String db;
private String sys;
private DataField(String xml, String db, String sys){
this.xml = xml;
this.db = db;
this.sys = sys;
}
public getXml(){
return this.xml;
}
public static DataField valueOfXml(String xml){
for (DataField d : this.values()){
if (d.xml.equals(xml)){ return d;}
}
}
bla, bla bla
}
这允许我做的是将字段名称DataField放在我的所有消息中,并能够映射在多个系统中调用该字段的内容。所以在我的XML中,它可能是firstname
,在我的数据库中,它可能被称为first_name
,但在我的外部接口系统中,它可能被称为first
。这种模式非常好地将所有这些结合在一起,并且以紧凑,类型安全的方式使这些类型的系统中的消息传递非常容易。
现在我不记得为什么Scala改变了枚举实现,但我记得当我读它时它是有意义的。但问题是,我将在Scala中使用什么来取代这种设计模式?我讨厌失去它,因为它对我在某一天写的很多系统都非常有用和基础。
感谢
答案 0 :(得分:5)
我设法为你的案件补充了这种替代品:
sealed class DataField(val xml: String, val db: String, val sys: String)
object DataField {
case object Field1 extends DataField("xmlField1", "dbField1", "system1Field")
case object Field2 extends DataField("xmlField2", "dbField2", "system2Field")
case object Field3 extends DataField("xmlField3", "dbField3", "system3Field")
val values = List(Field1, Field2, Field3)
def valueOfXml(xml: String) =
values.find(_.xml == xml).get
}
令人讨厌的是我们必须手动创建values
列表。但是,在这种情况下,我们可以做一些宏黑客攻击来减少样板:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object Macros {
def caseObjectsFor[T]: List[T] = macro caseObjectsFor_impl[T]
def caseObjectsFor_impl[T: c.WeakTypeTag](c: Context): c.Expr[List[T]] = {
import c.universe._
val baseClassSymbol = weakTypeOf[T].typeSymbol.asClass
val caseObjectSymbols = baseClassSymbol.knownDirectSubclasses.toList.collect {
case s if s.isModuleClass && s.asClass.isCaseClass => s.asClass.module
}
val listObjectSym = typeOf[List.type].termSymbol
c.Expr[List[T]](Apply(Ident(listObjectSym), caseObjectSymbols.map(s => Ident(s))))
}
}
然后我们可以这样做:
val values = Macros.caseObjectsFor[DataField]
而不是手动列出所有案例对象。
为此,必须将基类声明为sealed
。
答案 1 :(得分:2)
你可以随时做我做的事情,并继续用Java编写枚举。
在我的源代码树中的62个.java文件中,61个是枚举,另一个是package-info.java。