我在
Java中有以下界面
public interface IProperty<T extends Comparable<T>> { String getName(); Collection<T> getAllowedValues(); Class<T> getValueClass(); String getName(T value); }
并试图在scala中实现它,但无法让它工作
第一次尝试:
class EnumerationProperty1[T <: Enumeration](val enum: T,val name: String) extends IProperty[enum.Value] { override def getName = name override def getValueClass = classOf[enum.Value] override def getName(value: enum.Value): String = value.toString override def getAllowedValues: java.util.Collection[enum.Value] = enum.values.toList }
不编译时出错:找不到:值枚举
第二次尝试:
class EnumerationProperty2[T <: Enumeration](val enum: T,val name: String) extends IProperty[T#Value] { override def getName = name override def getValueClass = classOf[T#Value] override def getName(value: T#Value): String = value.toString override def getAllowedValues: java.util.Collection[T#Value] = enum.values.toList }
不使用Error编译:类型参数[T#Value]不符合特征IProperty的类型参数bounds [T<:Comparable [T]] 最后我找到了一种方法,但它对我来说看起来很难看:
object EnumerationPropertyAnonymous { def create[T <: Enumeration](enum: T,name: String) = { new IProperty[enum.Value] { override def getName = name override def getValueClass = classOf[enum.Value] override def getName(value: enum.Value): String = value.toString override def getAllowedValues: java.util.Collection[enum.Value] = enum.values.toList } } }
问题:
>这样做的正确方法是什么?
>为什么enum.Value在我的第一次尝试中不起作用,但在匿名类中使用时是否有效?
>为什么enum.Value和T#Value不一样?
>为什么编译器会抱怨T#Value与Comparable [T]不匹配,因为Value扩展了Ordered [Value],它扩展了Comparable [Value]?
解决方法
啊,使用路径依赖类型的乐趣……
枚举#Value是路径依赖类型.
这是Value的实际类型取决于Enumeration实现的当前实例.
因此,如果你有两个枚举
object A extends Enumeration { val first = Value(0,"first") } object B extends Enumeration { val first = Value(0,"first") }
以下条件返回false.
A.first == B.first A.first.isinstanceOf[B.first.type]
但这是事实
A.first.isinstanceOf[Enumeration#Value]
有关路径相关类型的更多信息,请参阅此article
对于问题:
@ 1)这取决于你想要完成的事情.一个快速的方法是与工厂.有点类似于你的“匿名”示例,但有点像scala-ish:
// it is recommended to use converters instead of conversions. import scala.collection.JavaConverters._ case class EnumPropertyFactory[T <: Enumeration](val enum: T) { def apply(name: String) = new EnumerationProperty(name) class EnumerationProperty(val name: String) extends IProperty[enum.Value] { override def getName = name override def getValueClass = classOf[enum.Value] override def getName(value: enum.Value): String = value.toString override def getAllowedValues: java.util.Collection[enum.Value] = enum.values.toList.asJavaCollection } } // can be used with something like val enum1PropertyFactory = EnumPropertyFactory(EnumOne) val foo = enum1PropertyFactory("foo") val bar = enum1PropertyFactory("bar")
@ 2)因为在第一个例子中,enum是一个构造函数参数,在第二个例子中它是一个本地val.记住java中类定义的样子:
class EnumerationProperty1<T extends Enumeration> extends IProperty<enum.Value> { public EnumerationProperty1(T enum,String name) { ... } }
@ 3)见上文:路径依赖类型
@ 4)我害怕,这有点高于我.但我敢打赌,它与Enumeration#Value有关,因为路径依赖,而voodoo用#;)完成