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

Scala类型系统-帮助理解类型别名上的不匹配,scala,types,Scala,Types,我是Scala类型系统的新手,我正试图通过这个JAXB编组示例来探索它。如果将参数的类型更改为toString为AnyRef,则该选项有效。但是,我想通过类型系统表示,toString的参数必须与concrete构造函数的类型参数的类型相同。有没有办法做到这一点 我不明白为什么下面的错误消息似乎表明typ=XMLMarshaller[TestObj]而不仅仅是TestObj。在我的调试器中,typ=TestObj。非常感谢您对这个特定问题的任何帮助或对这段代码的总体见解 error: type

我是Scala类型系统的新手,我正试图通过这个JAXB编组示例来探索它。如果将参数的类型更改为toString为AnyRef,则该选项有效。但是,我想通过类型系统表示,toString的参数必须与concrete构造函数的类型参数的类型相同。有没有办法做到这一点

我不明白为什么下面的错误消息似乎表明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)
  }
}
import javax.xml.bind.{Marshaller,JAXBContext}
导入java.io.{ByteArrayInputStream,StringWriter}
导入org.jboss.resteasy.plugins.providers.jaxb.json.JettisonMappedContext
导入javax.xml.bind.annotation.{XmlRootElement,XmlAccessorType,XmlAccessType}
抽象类XMarshaller{
val上下文:JAXBContext

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

您所拥有的类似于:

abstract class FooAbstract {
    type Type <: AnyRef
}

class FooConcrete[T<:AnyRef](implicit mt: Manifest[T]) extends FooAbstract {
    val Type = mt.erasure
}
奇怪的是Scala允许您无法重写类型,并且 让它完全抽象。我不确定这是故意的还是Scala
bug.

Owen,谢谢你的帮助。不过,这里对我来说还是有点神秘。首先,valueOf返回了正确的类型,尽管你解释的含义是具体的val类型没有覆盖抽象类型。这怎么可能?我不确定。我猜你指的是正确的运行时类型?那是这并不奇怪,因为运行时类型不受类型变量的影响。我不确定的是为什么将[typ]
转换为instanceof[typ]成功。可能是因为它将其转换为
AnyRef
,即没有做任何操作。
class FooConcrete[T<:AnyRef](implicit mt: Manifest[T]) extends FooAbstract {
    type Type = T
}