Переопределение метода перечисления в Scala 3

Есть ли способ переопределить метод в перечислении Scala 3, как в Java?

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

Может, есть другой способ добиться подобной функциональности?

3 ответа

Решение

Кажется, что то, что вы хотите, в настоящее время невозможно, но есть другие способы сделать это. Вы можете попробовать запечатанную черту старой школы с объектами, которые имеют приоритет.

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

Функцию также можно сделать параметром Test, хотя мне этот способ меньше нравится.

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

Другой способ сделать это - использовать один метод и сопоставление с образцом, как это сделали Джанлука Агуцци и Андрей Тюкин, хотя метод расширения не нужен.

Если calcдолжно быть функцией, я бы предложил первый подход или сопоставление с образцом, если вы считаете, что он вам больше подходит. Запечатанные черты также являются хорошим вариантом, если вы хотите переопределить несколько методов, поскольку вам не нужно отдельно выполнять сопоставление с образцом или объединять кучу лямбда-выражений в вызов конструктора. Если это не функция, мне кажется, лучше всего подойдет вторая.

В enumзапечатан, поэтому не может быть продлен постфактум, поэтому нет никаких причин для чего-либо. Просто соберите все дела в одном месте, а вместо нескольких 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

В scala 3 можно добиться аналогичного результата, комбинируя enum с участием extension method:

      enum Test {
  case One, Two
}

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

Надеюсь, я вам помог :)

Другие вопросы по тегам