Использование добавления функций / полей для перечисления случаев в Java, кроме переопределения? - PullRequest
3 голосов
/ 09 июля 2020

Случайно я обнаружил, что компилятор Java 1.8 допускает следующий синтаксис:

enum AnimalType {
    DOG {
        @Override
        public String toString() {
            return "I am a dog";
        }
    },
    CAT {
        @Override
        public String toString() {
            return "I am a cat";
        }

        public void doCatThings() {
            // ...
        }
    },
}

Переопределение toString() по отдельности работает отлично. Вызов AnimalType.DOG приводит к появлению строки «Я собака».

Однако, кроме этого, я не смог найти никакой информации о том, для чего можно использовать эту настройку случая перечисления. Обратите внимание на другой метод publi c для случая CAT. При определении любого другого метода или поля publi c кажется, что к нему нельзя получить доступ извне.

Так в чем же дело? Это просто технически правильный синтаксис, но бессмысленный?

Ответы [ 2 ]

4 голосов
/ 09 июля 2020

toString унаследовано от Object, но поведение по-прежнему полиморфно. c: DOG и CAT «печатают себя» по-разному. Теперь ваши собственные методы (например, sound() в следующем примере) будут иметь гораздо больший смысл, если вы будете использовать абстрактный метод на уровне определения AnimalType перечисления:

enum AnimalType {
    DOG {
        @Override
        public String toString() {
            return "I am a dog";
        }

        @Override
        public void sound() {
           System.out.println("Meowww");
        }
     
    },
    CAT {
        @Override
        public String toString() {
            return "I am a cat";
        }

        @Override
        public void sound() {
           System.out.println("Woof, I'm a barking dog");
        }
    };

    abstract void sound();
}

Теперь вы может добавить polymorphi c настраиваемое поведение в перечисление и использовать его, не зная фактического животного:


public class SampleClass {

    public static void doSound(AnimalType animal) {
       ...
       animal.sound();
    }
}

// usage:

SampleClass.doSound(AnimalType.DOG);

Фактическое использование может варьироваться, из моей головы, вы можете реализовать конечный автомат, анализируя перечисления являются токенами, вычисления, если перечисления являются геометрическими c фигурами (например, вычислить объем 3D-фигуры), а что нет. Это инструмент для java программистов, как и многих других. Используйте его с умом :)

1 голос
/ 09 июля 2020

Как объяснил ответ bij @MarkBramnik, основное использование - определение методов в самом типе перечисления, а затем предоставление каждому значению перечисления собственной реализации для него.

Как вы сами определили, еще один solid вариант использования - использовать это для предоставления настраиваемой реализации для каждого значения перечисления для унаследованных методов. Обратите внимание, что вы не ограничены только вещами из java.lang.Object - перечисления могут реализовывать интерфейсы!

public interface SoundSource {
    void play();
}

public enum Animal implements SoundSource {
    DOG {
        @Override public void play() {
            AudioSystem.play("woof.mp3");
        }
    }
}

, например.

EDIT: ** Хотя это звучит хорошо, на самом деле она не работает в java - оставляя ответ как есть, но воспринимайте его как функцию «было бы неплохо» **

Эта функция также полезна, потому что она позволяет перечислять значения служат дампом хранилища для методов, которые go концепт. Например:

enum Animal {
    DOG,
    CAT {
        public void doCatThings() { ... }
    }
}

Это в основном проблема с пространством имен: если у вас есть метод, который относится к кошкам как концепции, а не к другим животным, вам нужно поместить его где-нибудь . Вы можете сделать class CatUtils { public static void doCatThings() {} }, если хотите, но класс Utils - это немного запах кода. По крайней мере, это трудно обнаружить. Более удобное место для размещения таких служебных методов, , если у вас уже есть перечисление, выделенное для этой концепции, находится в самом значении перечисления; тогда вы можете позвонить Animal.CAT.doCatThings(); вместо CatUtils.doCatThings();, что немного лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...