Как выбрать базовый класс во время выполнения в зависимости от переменной экземпляра родительского класса в Java? - PullRequest
0 голосов
/ 07 мая 2020

Проблема : со следующими классами я пытаюсь выбрать базовый класс во время выполнения в зависимости от переменной экземпляра родительского класса в Java. Я считаю, что в OOPS должно быть какое-то фундаментальное свойство, которое может помочь мне достичь этого, которого мне просто не хватает.

    class Transaction{
       int id;
       enum transactionType;
    }

    class ATypeTransaction extends Transaction{
       /* bunch of instance variable specific to ATypeTransaction */
    }

    class BTypeTransaction extends Transaction{
       /* bunch of instance variable specific to BTypeTransaction */
    }
 /* The event can be triggered with any transactionType as declared in the enum TransactionType as each event would be associated with one transaction.*/
        class Event{
           int eventId;
           enum transactionType;
        }

В зависимости от transactionType, я должен подготовить Transaction Payload, и атрибуты будут разными для разных баз классы, как показано ниже.

Мой подход : я пытаюсь использовать что-то вроде этого (полиморфизм stati c в switch-case) в попытке разрешить экземпляр транзакции на основе Проблема с этим подходом в том, что я все еще не могу получить дочерний класс. Скорее я получаю родительский класс, который не дает мне получить доступ к атрибутам дочернего класса.

public Transaction selectTransaction(TransactionType transactionType){
        Transaction transaction;
        switch(transactionType) {
            case = "AType":
                transaction= new ATypeTransaction();
                break;
            case = "BType":
                transaction= new BTypeTransaction();
                break;
        }
   return transaction;
}

Пожалуйста, помогите мне с этой проблемой и предоставьте хороший дизайн для ее решения. Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 07 мая 2020

Если вы настроены на выбор типа возвращаемого объекта с помощью переключателя и типа перечисления, я думаю, что это будет лучшим решением:

public static enum TransactionType {
    AType,
    BType
}

public static class Transaction {
    public static void main(String[] args) {
        ATypeTransaction transA = selectTransaction(TransactionType.AType);
        BTypeTransaction transB = selectTransaction(TransactionType.BType);
        Transaction trans = selectTransaction(TransactionType.AType);

        transA.doA();
        transB.doB();
        ((ATypeTransaction)trans).doA();

        //The following will cause class cast exception
        ATypeTransaction transC = selectTransaction(TransactionType.BType);
        ((BTypeTransaction)trans).doB();
    }

    @SuppressWarnings("Unchecked")
    public static <T extends Transaction> T selectTransaction(TransactionType transactionType){
        switch(transactionType) {
            case AType:
                return (T) new ATypeTransaction();
                break;
            case BType:
                return (T) new BTypeTransaction();
                break;
        }
    }
}

public static class ATypeTransaction extends Transaction {
    public void doA() {}
}
public static class BTypeTransaction extends Transaction {
    public void doB() {}
}

К сожалению, если вы не знаете, является ли результат метода selectTransaction будет определенным c суперклассом класса Transaction (чтобы вы могли сохранить его в переменной правильного типа), или если вы проверите тип с помощью оператора instanceof (в случае переменной класса Transaction), вы ' Я рискую выбросить JVM ClassCastException.

0 голосов
/ 07 мая 2020

я думаю, что switch-case в java работает только с байтом, коротким, char, string и enum. Вы можете использовать экземпляр Operator в инструкции if. Но, возможно, есть лучшие решения, когда дело доходит до дизайна.

0 голосов
/ 07 мая 2020

По какой-то причине вы хотите, чтобы ваш API содержал такой метод, как Transaction selectTransaction(...).

Это предполагает, что ваши вызывающие абоненты не заботятся о конкретной реализации Transaction, но могут делать все, что захотят просто используя методы из типа Transaction, никогда не требуя ничего конкретного c из ATypeTransaction или BTypeTransaction.

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

Есть два возможных пути:

  • Отказаться от общего родительского класса Transaction и жить с двумя независимыми классами ATypeTransaction и BTypeTransaction или
  • Найдите варианты использования, в которых подтипы обрабатываются по-разному, создайте абстракцию (абстрактный метод) в родительском классе и реализуйте ее индивидуально в подклассах.
0 голосов
/ 07 мая 2020

поместите бизнес-логи c в свои данные:

class Transaction{
   int id;
   enum transactionType;

   public void handleTransaction() {
     //common code
   }
}

class ATypeTransaction extends Transaction{
   /* bunch of instance variable specific to ATypeTransaction */
   @Override       
   public void handleTransaction() {
     // access specific attributes
     super.handleTransaction();
   }
}
...