首页 > 解决方案 > Scala:继承的枚举对象不满足父特征

问题描述

我正在尝试在方法中使用 Enumeration 对象。枚举对象从特征扩展而来,该方法将特征作为参数。这是示例代码。

sealed trait canAdd
object DAdder extends Enumeration with canAdd
{
    type DAdder = Value
    val  P, Q = Value
}

class ClassTypeTest extends AnyFlatSpec with Matchers
{
    class AClass
    {
        def add(v: canAdd) = if(v.isInstanceOf[DAdder]) println("Got DAdder") else println("Got IAdder")
        def note(v: canAdd) = println("Got some canAdd trait object")
    }
    val aobj = new AClass
    val aseq: Seq[DAdder] = Seq(DAdder.P, DAdder.Q, DAdder.P)
    //*** Error in below line *****    
    aseq.foreach(aobj.add(_))
}

编译器给出以下错误:

Error:(23, 23) type mismatch;
 found   : x.x.DAdder.DAdder
    (which expands to)  x.x.DAdder.Value
 required: x.x.canAdd
    aseq.map(aobj.add(_))

我不应该能够在将特征作为参数的方法中传递继承特征的对象吗?我该如何解决?

标签: scalatypes

解决方案


Enumeration类不允许您扩展其值功能。基本上是:

abstract class Enumeratum {
  sealed trait Value { /* utilities */ }
  object Value { /* factory of Values */ }
 
  // utilities
}

由于您只能在Enumeratum课堂上进行控制,因此您无法扩展Value您所要求的 s 。

sealed trait您可以使用s 和case objects轻松拥有此功能

sealed trait DAdder extends canadd
object DAdder {

  case object P extends DAdder
  case object Q extends DAdder
}

但是,这会遗漏一些实用程序,例如通过名称查找值、列出所有值等。

这个问题由 Enumeratum 库解决,它要求您混合一些特征并粘贴一行 ( val values = findValues) 以具有 Enumeration 的所有功能等等

import enumeratum._

sealed trait DAdder extends canadd
  with EnumEntry // mixin here
object DAdder extends Enum[DAdder] { // and mixin here

  case object P extends DAdder
  case object Q extends DAdder

  val values = findValues // and one line calling macro
}

(还有一些特化的枚举应该将一些原语/字符串作为它们的值存储在 中enumeratum.values._)。

在 Scala 3 中,这可能看起来略有不同,因为它引入了enum关键字

sealed trait DAdder extends canadd
object DAdder {

  case object P extends DAdder
  case object Q extends DAdder
}

会变成

enum DAdder extends canadd {
  case P, Q
}

Scala 3 的枚举将ordinal定义方法,因此像 Enumeratum 这样的库将不得不提供更少的功能。(我想通过混合 Java 的 Enum 特征,您将可以访问,values所以其他一切都是扩展方法的问题)。


推荐阅读