gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 02:02:20 26 4
gpt4 key购买 nike

我在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
}

编译时出错:类型参数 [T#Value] 不符合 trait IProperty 的类型参数界限 [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]?
  • 最佳答案

    啊,使用路径依赖类型的乐趣......
    Enumeration#Value是路径依赖类型。
    那是 Value 的实际类型取决于 Enumeration 的当前实现实例.

    因此,如果您有两个 Enumerations

    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) 因为在第一个示例中枚举是构造函数参数,而在第二个示例中它是本地 val .记住类定义在 java 中的样子:
    class EnumerationProperty1<T extends Enumeration> extends IProperty<enum.Value> {
    public EnumerationProperty1(T enum, String name) { ... }
    }

    这里很清楚,为什么 enum在调用构造函数之前无法知道。

    @3) 见上文:路径依赖类型

    @4) 恐怕,这有点超出我的想象。但我敢打赌,这与 Enumeration#Value 有关。依赖路径并且使用 # 完成巫术;)

    关于scala - 为什么我不能在没有丑陋的匿名类的情况下在 Scala 中实现这个 Java 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35129402/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com