Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中将Java枚举作为类型参数引用_Java_Scala_Generics_Protocol Buffers - Fatal编程技术网

在Scala中将Java枚举作为类型参数引用

在Scala中将Java枚举作为类型参数引用,java,scala,generics,protocol-buffers,Java,Scala,Generics,Protocol Buffers,我想为protobuf编译器生成的enum实现一个瘦包装器,因为我需要对一些方法进行注释。 Protobuf生成最后一个类,所以我实现了一个新的泛型类,它存储一个枚举实例,而不是扩展枚举子类 Protobuf生成的类如下所示 public enum CardType implements com.google.protobuf.ProtocolMessageEnum { /** * <code>NONE = 0;</code> */ NON

我想为protobuf编译器生成的enum实现一个瘦包装器,因为我需要对一些方法进行注释。 Protobuf生成最后一个类,所以我实现了一个新的泛型类,它存储一个枚举实例,而不是扩展枚举子类

Protobuf生成的类如下所示

  public enum CardType
    implements com.google.protobuf.ProtocolMessageEnum {
  /**
   * <code>NONE = 0;</code>
   */
  NONE(0, 0)
  }
我实现了一个包装器类

object ProtoEnumWrapper {
  def fromString[T <: Enum[T] with ProtocolMessageEnum](s: String): ProtoEnumWrapper[T] =
    Enum.valueOf[T](classOf[T], s) match {
      case null => throw new InvalidStringForEnum(s"${s} is not value of ${classOf[T]}")
    }

  def fromProto[T <: Enum[T] with ProtocolMessageEnum](proto: T): ProtoEnumWrapper[T] =
    new ProtoEnumWrapper[T](proto)

  class InvalidStringForEnum(message: String) extends RuntimeException(message)
}

class ProtoEnumWrapper[T <: Enum[T] with ProtocolMessageEnum](proto: T) {
  override def equals(o: Any) = o match {
    case x: ProtoEnumWrapper[T] => proto == x.proto
    case e: T => proto == e
    case s: String => toString == s
    case _ => false
  }

  override def toString = proto.toString
}
但是,这会导致编译错误

Error:(7, 29) class type required but T found
    Enum.valueOf[T](classOf[T], s) match {
                            ^
Error:(8, 84) class type required but T found
      case null => throw new InvalidStringForEnum(s"${s} is not value of ${classOf[T]}")
                                                                                   ^
Error:(19, 47) value proto is not a member of jp.pocket_change.voucher.domain.ProtoEnumWrapper[T]
case x: ProtoEnumWrapper[T] => proto == x.proto
                                              ^

有一种叫做擦除的东西——因为它,当你的代码被编译成JVM字节码时,里面没有
T
的痕迹。大多数时候。但是在Scala中,有一个解决方法:您可以指定一个隐式的
Scala.reflect.ClassTag
,它由编译器生成并传递给相应的方法调用

我更新了代码中
ProtoEnumWrapper.fromString
ProtoEnumWrapper.fromProto
ProtoEnumWrapper
的签名:

object ProtoEnumWrapper {
  def fromString[T <: Enum[T] with ProtocolMessageEnum](s: String)(implicit ct: ClassTag[T]: ProtoEnumWrapper[T] = try {
    new ProtoEnumWrapper(Enum.valueOf[T](ct.runtimeClass, s))
  } catch {
    case e: IllegalArgumentException => throw new InvalidStringForEnum(s"${s} is not a value of ${ct.runtimeClass}")
  }

  def fromProto[T <: Enum[T] with ProtocolMessageEnum : ClassTag](proto: T): ProtoEnumWrapper[T] =
    new ProtoEnumWrapper[T](proto)

  class InvalidStringForEnum(message: String) extends RuntimeException(message)
}

class ProtoEnumWrapper[T <: Enum[T] with ProtocolMessageEnum : ClassTag](proto: T) {
  override def equals(o: Any) = o match {
    case x: ProtoEnumWrapper[T] => proto == x.proto
    case e: T => proto == e
    case s: String => toString == s
    case _ => false
  }

  override def toString = proto.toString
}
objectprotoEnumWrapper{
def fromString[T抛出新的InvalidStringForEnum(s“${s}不是${ct.runtimeClass}的值”)
}
def fromProto[T proto==e
案例s:String=>toString==s
大小写=>false
}
覆盖def toString=proto.toString
}

请注意这两种替代定义:
defa[T:ClassTag]
只是编写
defa[T](隐式ct:ClassTag[T])
的一种较短的方法,以防您的代码中不需要实际的
ct

我可能会关闭,因为我对Scala不太熟悉,但我知道您是如何尝试使用类型参数(T)在需要类型的位置(classOf)。谢谢,但此代码会导致另一个错误:(9,24)类型不匹配;找到:Class[$1],其中需要类型$1:Class[T]Enum.valueOf[T](ct.runtimeClass,s)匹配{^Ah是的,因为您将runtimeClass实例作为参数传递给另一个方法,所以还需要添加强制转换:
ct.runtimeClass.asInstanceOf[Class[T]]
。它看起来有点粗糙,但这样做是安全的。@Mekajiki,顺便说一句,您的
fromString
包含另一个关于通过
Enum获取值的问题。valueOf
,我更新了我的答案以解决它。
object ProtoEnumWrapper {
  def fromString[T <: Enum[T] with ProtocolMessageEnum](s: String)(implicit ct: ClassTag[T]: ProtoEnumWrapper[T] = try {
    new ProtoEnumWrapper(Enum.valueOf[T](ct.runtimeClass, s))
  } catch {
    case e: IllegalArgumentException => throw new InvalidStringForEnum(s"${s} is not a value of ${ct.runtimeClass}")
  }

  def fromProto[T <: Enum[T] with ProtocolMessageEnum : ClassTag](proto: T): ProtoEnumWrapper[T] =
    new ProtoEnumWrapper[T](proto)

  class InvalidStringForEnum(message: String) extends RuntimeException(message)
}

class ProtoEnumWrapper[T <: Enum[T] with ProtocolMessageEnum : ClassTag](proto: T) {
  override def equals(o: Any) = o match {
    case x: ProtoEnumWrapper[T] => proto == x.proto
    case e: T => proto == e
    case s: String => toString == s
    case _ => false
  }

  override def toString = proto.toString
}