简体   繁体   English

为什么我不能在没有丑陋的匿名类的情况下在Scala中实现这个Java接口

[英]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: 问题:

  1. What is the right way to do this? 这样做的正确方法是什么?
  2. Why enum.Value doesn't work in my first attempt, but does work when used in an anonymous class? 为什么enum.Value在我的第一次尝试中不起作用,但在匿名类中使用时是否有效?
  3. Why enum.Value and T#Value aren't the same? 为什么enum.Value和T#Value不一样?
  4. Why does the compiler complain about T#Value not matching Comparable[T], since Value extends Ordered[Value] which extends Comparable[Value]? 为什么编译器会抱怨T#Value与Comparable [T]不匹配,因为Value扩展了Ordered [Value],它扩展了Comparable [Value]?

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.

相关问题 Scala:如何实现一个包含scala“typed”类而没有类型参数的java接口 - Scala: how to implement a java interface that contains scala “typed” classes without their type parameters 如何在Scala中使用可变方法实现Java接口? - How can I implement a Java interface with variadic methods in Scala? 为什么不能在Scala中为匿名函数指定结果类型? - Why can't I specify a result type for an anonymous function in Scala? 为什么在Scala中的匿名函数内不能有for循环? - why can't I have a for loop inside an anonymous function in scala? 为什么我不能从Scala访问实现Java接口的类中声明的变量? - Why can't I access a variable declared in a class, which implements a Java interface, from Scala? 在Scala中将静态内部接口实现为匿名类 - Implement static inner interface as anonymous class in Scala 在 Scala 中,为什么我不能实现这样一个简单的通用函数? - In Scala, why can't I implement a trivial generic function like this? 为什么Scala编辑器中的Java类中的scala-ide刷新不能更改? - Why can't scala-ide refresh change in java classes in scala editor? Scala:为什么不能从复合类型成员创建匿名类? - Scala: why can't I create anonymous class from compound type member? Scala,无法实现通用的Java方法 - Scala, can't implement generic java method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM