Тип enum с телом класса и данными - PullRequest
0 голосов
/ 25 августа 2018
enum BankOperation { PLUS, MINUS }

public BankOperation getBankOperation(int oldAmount, int newAmount) {
    BankOperation operation = newAmount >= oldAmount ? BankOperation.PLUS : BankOperation.MINUS;
    int delta = Math.abs(newAmount - oldAmount);
    switch (operation) {
        case PLUS:
            System.out.println(String.format("Adding %s dollars", delta));
            break;
        case MINUS:
            System.out.println(String.format("Withdrawing %s dollars", delta));
            break;
    }
    return operation;
}

Примечание: пример нарочно прост и не выигрывает от использования enum методов.

У меня есть два BankOperation PLUS и MINUS с switch.Я получаю BankOperation на getBankOperation(5, 20);, чтобы я мог продолжить.

Мне было интересно, можно ли использовать методы на enum вместо switch, чтобы я мог получить BankOperation и соответствующая регистрация в цепочке:

BankOperation bankOperation = BankOperation.forOldAndNewAmount(5, 20).startProcessing();

, где

forOldAndNewAmount(5, 20) инициализирует перечисление и делает поле перечисления delta 15 a private int delta BankOperation

startProcessing() - это абстрактное method из BankOperation, которое соответствует System.out.println(String.format("Adding/Withdrawing %s dollars", delta)); в зависимости от BankOperation

. Мне показалось, что самое сложное - это печать delta 15 в теле enum без указания его в качестве параметра startProcessing() - возвращая PLUS и MINUS enum в startProcessing().

Ответы [ 3 ]

0 голосов
/ 25 августа 2018

Я думаю, вы ищете что-то подобное:

public class Bank {

enum BankOperation { 
    PLUS("Adding %s dollars"), 
    MINUS("Withdrawing %s dollars");

    private final String msg;

    BankOperation(final String msg) {
        this.msg = msg;
    }


    public String getMsg() {
        return msg;
    }
}

public BankOperation getBankOperation(int oldAmount, int newAmount) {
    BankOperation operation = newAmount >= oldAmount ? BankOperation.PLUS : BankOperation.MINUS;
    int delta = abs(newAmount - oldAmount);

    System.out.println(String.format(operation.getMsg(), delta));

    return operation;
}

}

0 голосов
/ 25 августа 2018

Константы перечисления являются подклассами самого (абстрактного) класса перечисления.Затем вы можете сделать что-то вроде

public enum BankOperation {

    DEPOSIT {
        @Override
        public void execute(Bank bank, Amount amount) {
            // do something
        }
    },

    WITHDRAW {
        @Override
        public void execute(Bank bank, Amount amount) {
            // do something else
        }
    };

    public abstract void execute(Bank bank, Amount amount);
}

// called like 
BankOperation.DEPOSIT.execute(bank, amount);

// or
BankOperation operation;
...
operation.execute(bank, amount

Так как класс enum является (абстрактным) родителем каждой его константы,.к enum можно добавить поля и конструкторы:

public enum BankOperation {

    DEPOSIT("Deposit") {
        @Override
        public void execute(Bank bank, Amount amount) {
            // do something
        }
    },

    WITHDRAW("Withdraw") {
        @Override
        public void execute(Bank bank, Amount amount) {
            // do something else
        }
    };

    private String name;

    private BankOperation(String theName) {
        this.name = theName;
    }

    public abstract void execute(Bank bank, Amount amount);

    public String getName() {
        return name;
    }
}

Также полезно добавить статические методы:

public enum BankOperation {

    DEPOSIT("Deposit") {
        ...
    },

    WITHDRAW("Withdraw") {
        ...
    };

    ...

    public static BankOperation get(Amount oldAmount, Amount newAmount) {
        // same amount being ignored for simplicity
        if (newAmount.isLessThan(oldAmount))
            return WITHDRAW;
        else
            return DEPOSIT;
    }
}
0 голосов
/ 25 августа 2018

В вашем реальном примере getBankOperation() - это обработка, за которую должно отвечать перечисление BankOperation.
Вам не нужен экземпляр Bank для его обработки.
Так что просто переместите этот метод какстатический метод перечисления:

enum BankOperation { PLUS, MINUS; 

     public static BankOperation getBankOperation(int oldAmount, int newAmount) {
            BankOperation operation = newAmount >= oldAmount ? BankOperation.PLUS : BankOperation.MINUS;
            int delta = Math.abs(newAmount - oldAmount);
            switch (operation) {
                case PLUS:
                    System.out.println(String.format("Adding %s dollars", delta));
                    break;
                case MINUS:
                    System.out.println(String.format("Withdrawing %s dollars", delta));
                    break;
            }
            return operation;
        }
    };

Теперь вы можете сделать:

BankOperation bankOperation = BankOperation.getBankOperation(5, 20);

Дополнительно эту часть можно переместить в метод перечисления:

switch (operation) {
    case PLUS:
        System.out.println(String.format("Adding %s dollars", delta));
        break;
    case MINUS:
        System.out.println(String.format("Withdrawing %s dollars", delta));
        break;
}

Itвыдаст:

enum BankOperation {

    PLUS {
        public String getOutput(int delta) {
            return String.format("Adding %s dollars", delta);
        }
    },
    MINUS {

        @Override
        public String getOutput(int delta) {
            return String.format("Withdrawing %s dollars", delta);
        }
    };

    public abstract String getOutput(int delta);

    public static BankOperation getBankOperation(int oldAmount, int newAmount) {
        BankOperation operation = newAmount >= oldAmount ? BankOperation.PLUS : BankOperation.MINUS;
        int delta = Math.abs(newAmount - oldAmount);
        System.out.println(operation.getOutput(delta));
        return operation;
    }
}

О вашем комментарии:

Возможно ли, вы дадите мне знать, как добиться "превращения дельты в private int delta поле перечисленияBankOperation при инициализации с помощью forOldAndNewAmount(5, 20), тогда я могу вызвать startProcessing() в цепочке, не делая его параметром "?

Вы не должны этого делать, потому что перечисления представляют постоянные значения.Перезаписанные значения перечислений во время обработки неясны и могут создать побочные эффекты, если ваше приложение является многопоточным или станет многопоточным.
В качестве альтернативы вы можете использовать класс, который переносит BankOperation и дельту (BankOperationComputed) и чтоforOldAndNewAmount() возвращается.

BankOperation getBankOperation() будет лучше называться BankOperationComputed computeBankOperation():

public static BankOperationComputed computeBankOperation(int oldAmount, int newAmount) {
    BankOperation operation = newAmount >= oldAmount ? BankOperation.PLUS : BankOperation.MINUS;
    int delta = Math.abs(newAmount - oldAmount);
    return new BankOperationComputed(operation, delta);
}

BankOperationComputed

public class BankOperationComputed {
      private final BankOperation operation;
      private final int delta; 

      BankOperationComputed (BankOperation operation, int delta){
         this.operation = operation;
         this.delta = delta;
      }
      public void startProcessing(){
           System.out.println(operation.getOutput(delta));
      }
}

Теперь вы можете сделать это:

BankOperation.computeBankOperation(5, 20) // returns BankOperationComputed 
             .startProcessing();  // uses the enum under the hoods
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...