如何创建类型化工厂方法构造函数的类层次结构,并使用抽象类型从Scala访问它们?

如何创建类型化工厂方法构造函数的类层次结构,并使用抽象类型从Scala访问它们?,scala,Scala,(本质上,我需要这两个问题的某种综合(,),但我自己不够聪明,无法将它们结合起来。) 我在Scala中有一组JAXB表示,如下所示: abstract class Representation { def marshalToXml(): String = { val context = JAXBContext.newInstance(this.getClass()) val writer = new StringWriter context.createMarshal

(本质上,我需要这两个问题的某种综合(,),但我自己不够聪明,无法将它们结合起来。)

我在Scala中有一组JAXB表示,如下所示:

abstract class Representation {
  def marshalToXml(): String = {
    val context = JAXBContext.newInstance(this.getClass())
    val writer = new StringWriter
    context.createMarshaller.marshal(this, writer)
    writer.toString()
  }
}

class Order extends Representation {
  @BeanProperty
  var name: String = _
  ...
}
class Invoice extends Representation { ... }
val order = UnmarshalXml(xml).toRepresentation[T](typeOfT)
我遇到的问题是我的解组“构造函数”方法:

具体来说,我不知道如何将这些解组方法以一种类型安全且干燥的方式附加到我的每个类,然后从Scala调用它们(希望有时只使用抽象类型信息)。换句话说,我想这样做:

val newOrder = Order.unmarshalFromJson(someJson)
更雄心勃勃地说:

class Resource[R <: Representation] {
    getRepresentation(marshalledData: String): R = 
        {{R's Singleton}}.unmarshalFromXml(marshalledData)
}

class Resource[R关键是不要尝试将方法附加到类,而是将其作为参数传入。指示所需的类型,并让类型系统处理传入的操作。我尝试使解组调用看起来有点像DSL

val order = UnMarshalXml( xml ).toRepresentation[Order]
下面是一段完全可测试的代码片段

abstract class Representation {
  def marshalToXml(): String = {
      val context = JAXBContext.newInstance(this.getClass)
      val writer = new StringWriter
      context.createMarshaller.marshal(this, writer)
      writer.toString
  }
}

@XmlRootElement
class Order extends Representation {
  @BeanProperty
  var name: String = _
}

case class UnMarshalXml( xml: String ) {
  def toRepresentation[T <: Representation](implicit m:Manifest[T]): T = {
    JAXBContext.newInstance(m.erasure).createUnmarshaller().unmarshal(
      new StringReader(xml)
    ).asInstanceOf[T]
  }
}

object test {
  def main( args: Array[String] ) {
    val order = new Order
    order.name = "my order"
    val xml = order.marshalToXml()
    println("marshalled: " + xml )
    val received = UnMarshalXml( xml ).toRepresentation[Order]
    println("received order named: " + received.getName )
  }
}
抽象类表示法{
def marshalToXml():字符串={
val context=JAXBContext.newInstance(this.getClass)
val编写器=新的StringWriter
context.createMarshaller.Marshall(这个,编写器)
作者:托斯特林
}
}
@XmlRootElement
类顺序扩展了表示{
@豆性
变量名称:字符串=_
}
案例类解组xml(xml:String){

def toRepresentation[T下面是Neil代码的更新版本,我使用它来支持第二个用例和第一个用例:

case class UnmarshalXml(xml: String) {

  def toRepresentation[T <: Representation](implicit m: Manifest[T]): T =
    toRepresentation[T](m.erasure.asInstanceOf[Class[T]])

  def toRepresentation[T <: Representation](typeT: Class[T]): T =
    JAXBContext.newInstance(typeT).createUnmarshaller().unmarshal(
      new StringReader(xml)
    ).asInstanceOf[T]
}
但对于基于抽象类型的用法,您也可以这样使用:

abstract class Representation {
  def marshalToXml(): String = {
    val context = JAXBContext.newInstance(this.getClass())
    val writer = new StringWriter
    context.createMarshaller.marshal(this, writer)
    writer.toString()
  }
}

class Order extends Representation {
  @BeanProperty
  var name: String = _
  ...
}
class Invoice extends Representation { ... }
val order = UnmarshalXml(xml).toRepresentation[T](typeOfT)

(您在声明
T
时使用另一个
implicit Manifest
抓取并存储
typeOfT

谢谢Neil-我真的很喜欢您使用case类代替我笨拙的singleton想法的方法。您的示例运行良好-但不幸的是,我无法将其用于我的第二个(更困难)用例:
class-Resource[R嗨,尼尔-我找到了答案。将它作为另一个答案发布在下面。
val order = UnmarshalXml(xml).toRepresentation[T](typeOfT)