Создание перечисления Java в Scala

мое рабочее место экспериментировало в переходе от Java к Scala для некоторых задач, и это хорошо работает для того, что мы делаем. Однако некоторые существующие методы ведения журнала ожидают java.lang.Enum. Метод ведения журнала определен в базовом классе (Java), и подклассы могут определять свои собственные перечисления, которые регистратор будет отслеживать во всех экземплярах в нескольких потоках/машинах.

это работает так в Java:

public class JavaSubClass extends JavaBaseClass {
    enum Counters {
        BAD_THING,
        GOOD_THING
    }

    public void someDistributedTask() {
        // some work here
        if(terribleThing) {
            loggingMethod(Counters.BAD_THING)
        } else {
            loggingMethod(Counters.GOOD_THING)
            // more work here
        }
    }
}

затем, когда задача будет завершена, мы сможем увидеть это

BAD_THING: 230
GOOD_THING: 10345

есть ли способ воспроизвести это в Scala, либо создав Java Enums или преобразование из Enumeration to Enum? Я попытался расширить Enum напрямую, но он, кажется, запечатан, так как я получаю ошибку в консоли:

error: constructor Enum in class Enum cannot be accessed in object $iw
Access to protected constructor Enum not permitted because
enclosing object $iw is not a subclass of 
class Enum in package lang where target is defined

3 ответов


Если вам нужно перечисление java, то вам нужно написать его на Java. Есть вещи, которые вы можете сделать в Scala, чтобы заменить варианты использования of Enum, но в Scala нет ничего, что повторяет механику Java Enum.


Перечисления Java

для класса enum Counter было бы лучше, чем Counters - каждого значения enum представляет особой борьбы.

когда javac компилирует enum класс, это:

  1. компилируется в обычный класс java (например. Counter), содержащий все конструкторы, методы, другие члены перечисления (если есть)
  2. каждого enum значение (GOOD_THING, BAD_THING) является


хотя это, вероятно, не очень хорошая идея (см. другие сообщения для реальных хороших идей), это is можно продлить java.lang.Enum в Scala. Ваш код работал бы, если бы вы поместили класс и его сопутствующий объект в одну и ту же единицу компиляции (в REPL каждый оператор выполняется в своей собственной единице компиляции, если вы не используете :paste режим).

если вы используете :paste mode и вставить в следующий код, Scala с удовольствием скомпилирует это:

sealed class AnEnum protected(name: String, ordinal: Int) extends java.lang.Enum[AnEnum](name, ordinal)
object AnEnum {
  val ENUM1 = new AnEnum("ENUM1",0)
  case object ENUM2 extends AnEnum("ENUM2", 1) // both vals and objects are possible
}

однако взаимодействие Java, вероятно, не будет удовлетворительным. Компилятор Java добавляет static values и valueOf методы новые enum классы и гарантирует, что имена и ординалы верны, чего Scala не будет.

даже если вы сами выполните эти шаги, Java не будет доверять вашему перечислению, потому что у класса нет ENUM модификатор. Это значит, что Class::isEnum скажет, что ваш класс не является перечислением, которое повлияет на static Enum::valueOf способ, например. Оператор switch Java также не будет работать с ними (хотя сопоставление шаблонов Scala должно работать, если значения перечисления являются объектами case).