加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

我一直在使用Scala替换Java枚举模式

发布时间:2020-12-16 09:06:37 所属栏目:安全 来源:网络整理
导读:在 Java中,我做了很多数据集成工作.一直出现的一件事是在多个系统之间映射数据.所以我经常做这样的事情 public enum DataField{ Field1("xmlField","dbField","system1Field"; private String xml; private String db; private String sys; private DataFiel
在 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,但在我的外部接口系统中,它可能首先被调用.这种模式非常好地将所有这些结合在一起,并且以紧凑,类型安全的方式使这些类型的系统中的消息传递变得非常容易.

现在我不记得为什么Scala改变了枚举实现,但我记得当我读它时它是有意义的.但问题是,我将在Scala中使用什么来取代这种设计模式?我讨厌失去它,因为它对我在某一天写的很多系统都非常有用和基础.

谢谢

解决方法

我设法为你的案件补充了这种替代品:

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
}

令人讨厌的是我们必须手动创建值列表.但是,在这种情况下,我们可以做一些宏黑客攻击来减少样板:

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]

而不是手动列出所有案例对象.

为此,必须将基类声明为密封.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读