[英]Why can't I implement this Java interface in Scala without ugly anonymous classes
I have the following interface in Java 我在Java中有以下界面
public interface IProperty<T extends Comparable<T>> {
String getName();
Collection<T> getAllowedValues();
Class<T> getValueClass();
String getName(T value);
}
And trying to implement it in scala, but can't get it to work 并试图在scala中实现它,但无法让它工作
First attempt: 第一次尝试:
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
}
Doesn't compile with Error: not found: value enum 不编译时出错:找不到:值枚举
Second attempt: 第二次尝试:
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
}
Doesn't compile with Error: type arguments [T#Value] do not conform to trait IProperty's type parameter bounds [T <: Comparable[T]] 不使用Error编译:类型参数[T#Value]不符合特征IProperty的类型参数bounds [T <:Comparable [T]]
Finally i figured out a way to do it but it looks pretty ugly to me: 最后我找到了一种方法,但它对我来说看起来很难看:
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
}
}
}
Questions: 问题:
Ah, the joys of working with path dependent types ... 啊,使用路径依赖类型的乐趣......
Enumeration#Value
is a path dependent type. Enumeration#Value
是路径依赖类型。 That is the actual type of Value
depends on the current instance of the implementation of Enumeration
. 这是
Value
的实际类型取决于Enumeration
实现的当前实例。
Thus if you have two Enumerations
like 因此,如果你有两个
Enumerations
object A extends Enumeration {
val first = Value(0, "first")
}
object B extends Enumeration {
val first = Value(0, "first")
}
the following conditions return false
. 以下条件返回
false
。
A.first == B.first
A.first.isInstanceOf[B.first.type]
but this is true 但这是事实
A.first.isInstanceOf[Enumeration#Value]
For more about path dependent types, refer to this article 有关路径依赖类型的更多信息,请参阅本文
To the questions: 对于问题:
@1) that depends on what you are trying to accomplish. @ 1)这取决于你想要完成的事情。 A quick way to do it would be with a factory.
一个快速的方法是与工厂。 Somewhat similar to your 'anonymous' example, but a bit more scala-ish:
有点类似于你的“匿名”示例,但有点像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) Because in the first example enum is a constructor parameter and in the second example it's a local val
. @ 2)因为在第一个例子中,enum是一个构造函数参数,在第二个例子中它是一个本地
val
。 Remember what the class definition would look like in java: 记住java中类定义的样子:
class EnumerationProperty1<T extends Enumeration> extends IProperty<enum.Value> {
public EnumerationProperty1(T enum, String name) { ... }
}
Here it is clear, why enum
cannot be known before the constructor has been called. 这里很清楚,为什么在调用构造函数之前无法知道
enum
。
@3) see above: path dependent types @ 3)见上文: 路径依赖类型
@4) I'm afraid, that is a bit above me. @ 4)我害怕,这有点高于我。 But I'd bet some that it has to do with
Enumeration#Value
being path dependent and the voodoo done with #
;) 但我敢打赌,它与
Enumeration#Value
因为路径依赖,而voodoo用#
;)完成
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.