如何解决编译时的类型错误:A到T?

问题描述

我有一个供Tuple使用的json序列化程序。它首先在Tuple上进行反思,并构建一个函数,该函数给定Tutu的一些元数据,它将返回(TypeAdapter,值)对的列表。 (TypeAdapter是一种特定于类型的东西,它呈现值。)如下所示:

def extractTuple(p: Product): (Product)=>List[(TypeAdapter[_],Any)] = {
  val reflected = reflectOnTuple(tupleClass)  // extract a bunch of reflected Metadata
  val tupleFieldInfo = reflected.tupleFieldInfo
  tupleFieldInfos match {
    case 1 =>
      (p: Product) => 
        List( (getTypeAdapterFor(tupleFieldInfo(0)),p.asInstanceOf[Tuple1[_]]._1) )
    case 2 =>
      (p: Product) => 
        List( (getTypeAdapterFor(tupleFieldInfo(0)),p.asInstanceOf[Tuple1[_]]._1),(getTypeAdapterFor(tupleFieldInfo(1)),p.asInstanceOf[Tuple1[_]]._2) )
    //... and so on to Tuple23
  }
}

在JSON序列化程序中,我有一个writeTuple()函数,如下所示。从理论上讲,它应该是按原样工作的,但是...我在fieldValue上遇到编译错误,说当期望值是1.T时,它的类型为Any。

TypeAdapter看起来像:

trait TypeAdapter[T] {
  def write[WIRE](
      t:      T,writer: Writer[WIRE],out:    mutable.Builder[WIRE,WIRE]): Unit
}
class JsonWriter() {
  def writeTuple[T](t: T,writeFn: (Product) => List[(TypeAdapter[_],Any)],out: mutable.Builder[JSON,JSON]): Unit = {
    out += "[".asInstanceOf[JSON]
    var first = true
    writeFn(t.asInstanceOf[Product]).foreach { case (fieldTA,fieldValue) =>
      if (first)
        first = false
      else
        out += ",".asInstanceOf[JSON]
      fieldTA.write(fieldValue,this,out) // <<-- this blows up (compile) on fieldValue because it's type Any,not some specific field Type
    }
    out += "]".asInstanceOf[JSON]
  }
}

如何使TypeAdapter确信该字段是正确的类型?

解决方法

尝试对类型变量tp使用类型模式(小写)

class JsonWriter() extends Writer[JSON] {
  def writeTuple[T](t: T,writeFn: (Product) => List[(TypeAdapter[_],Any)],out: mutable.Builder[JSON,JSON]): Unit = {
    ...
    writeFn(t.asInstanceOf[Product]).foreach { case (fieldTA: TypeAdapter[tp],fieldValue) =>
      ...
      fieldTA.write(fieldValue.asInstanceOf[tp],this,out)
    }
    ...
  }
}

T代替

class JsonWriter() extends Writer[JSON] {
  def writeTuple[T](t: T,JSON]): Unit = {
    ...
    writeFn(t.asInstanceOf[Product]).foreach { case (fieldTA: TypeAdapter[T],fieldValue) =>
      ...
      fieldTA.write(fieldValue.asInstanceOf[T],out)
    }
    ...
  }
}

似乎您实际上并没有在T中使用writeTuple[T]。也许您可以尝试单态def writeTuple(t: Product...,而且如果您要指定(TypeAdapter[_],Any)实际上是(TypeAdapter[U],U)且在元组的两个元素中都具有相同的U,则可以尝试存在类型{{ 1}}。所以尝试

(TypeAdapter[U],U) forSome {type U}
,

Dmytro,您的答案非常接近!不幸的是,第一个或第二个选项均未编译。我认为3rd可以正常工作,除非...我实际上是在使用Dotty而不是Scala,并且Dotty消除了存在类型。

因此,我尝试了以下操作,并成功了。它知道它的类型,因此涉及修改TypeAdapter:

trait TypeAdapter[T] {
  type tpe = T
  def write[WIRE](
      t:      T,writer: Writer[WIRE],out:    mutable.Builder[WIRE,WIRE]): Unit
  inline def castAndWrite[WIRE]( 
      v:      Any,WIRE]): Unit = 
    write(v.asInstanceOf[tpe],writer,out)
}

从JsonWriter调用castAndWrite()可以调用正确类型的write()机制。