【问题标题】:How to get a class from a bounded generic type如何从有界泛型类型中获取类
【发布时间】:2013-06-24 05:38:21
【问题描述】:

我正在尝试为 Json4s 编写一个通用的自定义序列化程序,它可以处理类型为 T <: enum java enum.valueof t>

class EnumSerializer[T <: Enum[T]](implicit m: Manifest[T]) extends Serializer[T] {

  val enumerationClass: Class[_ <: Enum[T]] = m.runtimeClass.asInstanceOf[Class[T]]

  def deserialize(implicit format: Formats) :  PartialFunction[(TypeInfo, JValue), T] = {
    case (t @ TypeInfo(enumerationClass, _), json) => {
      json match {
        case JString(value) => Enum.valueOf(enumerationClass, value.toUpperCase()).asInstanceOf[T]
        case value => throw new MappingException(s"Can't convert $value to $enumerationClass")
      }
    }
  }

  def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
    case i : Enum[T] => JString(i.name())
  }
}

但我得到以下编译错误:

inferred type arguments [_0] do not conform to method valueOf's type parameter bounds [T <: Enum[T]]
case JString(value) => Enum.valueOf(enumerationClass, value.toUpperCase()).asInstanceOf[T]

我不知道如何让 enumerationClass 具有正确的类型。

【问题讨论】:

    标签: scala generics enums


    【解决方案1】:

    enumerationClass 在您的deserialize 方法中shadows 在其外部定义val enumerationClass。您的代码相当于:

    case (t @ TypeInfo(a, _), json) => {
      json match {
        case JString(value) => Enum.valueOf(a, value.toUpperCase()).asInstanceOf[T]
        case value => throw new MappingException(s"Can't convert $value to $enumerationClass")
      }
    }
    

    这不是您想要的:这将始终匹配,因为您不限制类。您需要将 enumerationClass 设为稳定标识符,即此处将其设为大写。请参阅this questionanswer 了解更多信息。

    class EnumSerializer[T <: Enum[T]](implicit m: Manifest[T]) extends Serializer[T] {
    
      val EnumerationClass = m.runtimeClass.asInstanceOf[Class[T]]
    
      def deserialize(implicit format: Formats) :  PartialFunction[(TypeInfo, JValue), T] = {
        case (t @ TypeInfo(EnumerationClass, _), json) => {
          json match {
            case JString(value) => Enum.valueOf(EnumerationClass, value.toUpperCase()).asInstanceOf[T]
            case value => throw new MappingException(s"Can't convert $value to $enumerationClass")
          }
        }
      }
    
      ...
    }
    

    【讨论】:

    • 谢谢,我什至没有意识到大写字母变量名在 Scala 中意味着什么。实际上,我在原始代码中就是这样(它基于其他人编写的不太通用的东西),但认为这只是一种奇怪的风格,所以我在添加通用部分之前对其进行了更改,然后想知道为什么它不起作用:)。
    【解决方案2】:

    尝试将enumerationClass 声明为:

    val enumerationClass: Class[T] = m.runtimeClass.asInstanceOf[Class[T]]
    

    您已经知道Manifest 的runtimeClass 是T 类型,所以我不确定您为什么将其声明为val enumerationClass: Class[_ &lt;: Enum[T]]Enum.valueOf 不能使用通配符类型,这就是您看到该错误的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-05
      • 2013-04-17
      • 1970-01-01
      • 2011-01-24
      • 2020-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多