【问题标题】:Scala 3 enum method overrideScala 3枚举方法覆盖
【发布时间】:2021-07-18 15:48:22
【问题描述】:

有没有办法像在 Java 中一样覆盖 Scala 3 枚举中的方法?

public enum Test {

    ONE {
        @Override
        public int calc() {
            return 1;
        }
    },
    TWO {
        @Override
        public int calc() {
            return 2;
        }
    };

    public abstract int calc();
}

我尝试过类似的方法,但没有结果。也没有在文档中找到任何关于枚举方法覆盖的信息。

enum Test {
  def calc(): Int ={
    0
  }
  case One
    override def calc(): Int ={
      1
    }
  case Two
    override def calc(): Int ={
      2
    }
}

也许还有其他方法可以实现类似的功能?

【问题讨论】:

  • 我不这么认为,尽管它可能是一个方便的功能。我建议现在只使用密封特征和案例类。
  • 不,这是不可能的。如果你想要那个功能,Java 和 Kotlin 可以提供,并且有很多方法可以在 Scala 中创建这个功能。但是 Scala 枚举中不允许​​有可选的匿名类。
  • 也可以将calc作为参数传给Test
  • 如果你的枚举有一个非常复杂的逻辑,你发现覆盖比匹配更清晰,那么你可能一开始就不应该使用枚举。

标签: scala enums anonymous-class scala-3


【解决方案1】:

enum 是密封的,所以事后不能扩展,所以override 没有任何理由。只需将所有案例收集在一个地方,而不是多个override-methods,而是编写一个涵盖所有案例的单一方法:

enum A:
  case X(x: Int)
  case Y(y: String)
  def foo: String = this match {
    case X(x) => s"X = ${x}"
    case Y(y) => y
  }

val x = new A.X(42)
val y = new A.Y("y")
println(x.foo) // X = 42
println(y.foo) // y

【讨论】:

  • 感谢您的回答,但是如果枚举案例很多,每个方法都大于一行,它仍然看起来不错吗?
  • @AndreiYusupau 我认为“是”,因为 1. 不必为每个案例类复制 override def calc(): Int ={-签名。 2. match 是使用枚举的自然方式,这就是它们应该被使用的方式。在enum本身的声明中不需要偏离标准的match-case
【解决方案2】:

您想要的似乎目前无法实现,但还有其他方法可以做到。您可以尝试使用覆盖 calc 的对象的老式密封特征。

sealed trait Test:
  def calc: Int
object One extends Test:
  def calc = 1
object Two extends Test:
  def calc = 2

函数calc也可以作为Test的参数,虽然我不太喜欢这种方法。

enum Test(calc: () => Int):
  case One extends Test(() => 1)
  case Two extends Test(() => 2)

另一种方法是通过单一方法和模式匹配,就像 gianluca aguzzi 和 Andrey Tyukin 所做的那样,尽管不需要扩展方法。

如果calc 必须是一个函数,我会建议第一种方法,或者如果你觉得它更适合你,则建议使用模式匹配。如果您想覆盖多个方法,密封特征也是一个不错的选择,因为您不需要单独进行模式匹配或将一堆 lambdas 集中到构造函数调用中。如果它不是一个函数,我觉得第二个效果最好。

【讨论】:

    【解决方案3】:

    在 scala 3 中,您可以将 enumextension method 结合起来获得类似的结果:

    enum Test {
      case One, Two
    }
    
    extension (test: Test)
      def calc() : Int = test match {
        case Test.One => 1
        case Test.Two => 2
      }
    
    

    希望对你有帮助:)

    【讨论】:

    • 我根本不明白为什么需要扩展方法。 calc 方法很容易成为 Test 的一部分,如果你不覆盖它的话。
    猜你喜欢
    • 1970-01-01
    • 2016-09-23
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    相关资源
    最近更新 更多