Scala类型系统-帮助理解类型别名不匹配



我是Scala类型系统的新手,我正试图通过这个JAXB编组示例来探索它。如果您将参数的类型从toString更改为AnyRef,它就会起作用。然而,我想通过类型系统表示,toString的参数必须与具体构造函数的类型参数相同。有办法做到这一点吗?

我不明白为什么下面的错误消息似乎指示typ=XMLMarshaller[TestObj]而不仅仅是TestObj。在我的调试器中,typ=TestObj。我们非常感谢您对这段代码的任何具体问题或见解的帮助!

error: type mismatch;  found   : TestObj  required: _1.typ where val
_1: XMLMarshaller[TestObj]
           val o = new XMLMarshaller[TestObj]().toString(new TestObj("hello","world"))

这是代码,只需粘贴到REPL:

import javax.xml.bind.{Marshaller, JAXBContext}
import java.io.{ByteArrayInputStream, StringWriter}
import org.jboss.resteasy.plugins.providers.jaxb.json.JettisonMappedContext
import javax.xml.bind.annotation.{XmlRootElement, XmlAccessorType, XmlAccessType}
abstract class XMarshaller {
  val context:JAXBContext
  type typ <: AnyRef
  def toString(obj:typ): String = {
    val marshaller:Marshaller = context.createMarshaller()
    val sw = new StringWriter
    marshaller.marshal(obj, sw)
    sw.toString
  }
  def valueOf(xmlString:String): typ = {
    val marshaller = context.createUnmarshaller()
    marshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes())).asInstanceOf[typ]
  }
}
class XMLMarshaller[T](implicit mT:Manifest[T]) extends XMarshaller {
  val typ = mT.erasure
  val context = JAXBContext.newInstance(typ)
}
class JSONMarshaller[T](implicit mT:Manifest[T]) extends XMarshaller {
  val typ = mT.erasure
  val context = new JettisonMappedContext(typ)
}
@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
case class TestObj(x:String, y:String){
  def this() {this("","")}
}
object Test {
  def main(args: Array[String]) {
    val o = new XMLMarshaller[TestObj]().toString(new TestObj("hello","world"))
    println(o)
  }
}

由于Scala的语法工作方式,类可以具有类型成员和值具有相同名称的成员,并且不创建任何名称冲突(您可以始终根据上下文判断其含义)。

你所拥有的类似于:

abstract class FooAbstract {
    type Type <: AnyRef
}
class FooConcrete[T<:AnyRef](implicit mt: Manifest[T]) extends FooAbstract {
    val Type = mt.erasure
}

其中CCD_ 1不覆盖类型成员CCD_。你真的想要

class FooConcrete[T<:AnyRef](implicit mt: Manifest[T]) extends FooAbstract {
    type Type = T
}

奇怪的是,Scala允许您无法覆盖类型,并且让它完全抽象。我不确定这是故意的还是Scala程序错误

最新更新