通过隐式扩展

时间:2016-01-08 13:54:36

标签: scala shapeless

Person模型case class通过REST端点向客户端公开。

scala> case class Person(firstname: String, lastname: String)
defined class Person

现在,其中一项内部服务希望"丰富"这个Person case class并为其添加社会安全号码。但是,浓缩只是为了从一个服务中填充社会安全号码并将其传递给另一个服务。

立即考虑将ssn属性添加到Person,如下所示 - 但是,Person给出Person时不希望这种情况暴露给端点消费者,并且SSN绝不可见用户调用公开case class Person(firstname: String, lastname: String, ssn: String) 数据的REST端点。

Person

因此,另一个想法是如下所述丰富scala> implicit class ExtendedPerson(person: Person){ | val SSN : String = "" | } defined class ExtendedPerson 案例类

Service1.findPerson

然后implicit API将在范围内Person,并希望准备val person = Person(firstName="Joe",lastname="Doe", ssn ="123-456-0000") ,如下所示

Service2.moreWorkWithPerson(person,other arguments)

然后

Service2.moreWorkWithPerson

然后ssn=123-456-0000希望从person参数中获取Person case class

在Scala中实现此目的的正确方法是什么,而不修改CREATE SEQUENCE MY_SPECIAL_COUNTER START WITH 100 INCREMENT BY -1 MAXVALUE 100 MINVALUE 0 NOCYCLE NOCACHE ORDER ; 的定义?可以无形帮忙吗?任何指针都会受到赞赏吗?

3 个答案:

答案 0 :(得分:1)

SSN作为ExtendedPerson中的val没有多大意义,相反它应该是一个使用人员名字和姓氏来查询你的数据库的函数。鉴于您的数据库速度很慢而且您可能不止一次调用Person.SSN,我建议不要使用此模式,因为每次调用.SSN时它都会查询您的数据库。相反,我会为Person编写一个隐式转换器来更明确地转换。

case class ExtendedPerson(basicInfo: Person,ssn: String)

implicit class PersonHelper(person: Person) extends AnyVal{
 def extended = {
   val ssn = DB.querySSN(...)
   ExtendedPerson(person,ssn)
 }
}


val person: ExtendedPerson = Person("John","Doe").extended

//person = ExtendedPerson(Person("John","Doe"),"123-456-0000"")

注意:代码是写在心里的,但在逻辑上应该是正确的

答案 1 :(得分:0)

看来你正在思考这个问题。这有什么问题?

case class Person(firstname: String, lastname: String, ssn: Option[String] = None);

现在,在REST处理程序中,您执行return Person("John", "Doe"),在其他服务中执行:return Person("John", "Doe", Some("111-11-1111"))

答案 2 :(得分:0)

也许你应该只向客户公开一个不同的类。

case class Person(firstname: String, lastname: String, ssn: String) {
  def toClient = ClientPerson(firstname, lastname)
}

case class ClientPerson(firstname: String, lastname: String)

object RESTService {
  def getPerson(id: String): ClientPerson = {
    val p: Person = DB.getPerson(id)
    p.toClient
  }
}