Java полиморфные методы - PullRequest
0 голосов
/ 15 июня 2009

В Java у меня есть абстрактный класс с именем Operation и три его подкласса, называемые OperationActivation, OperationPayment и OperationSendEmail.

ДОБАВЛЕНО ОТ КОММЕНТАРИИ: Объекты * операции являются объектными компонентами EJB, поэтому внутри них не может быть бизнес-логики.

Нет, я хочу создать класс процессора следующим образом:

public class ProcessOperationService {

public void processOperation(Operation operation) {
    out.println("process Operation");
    process(operation);
}

public void process(OperationActivation operationActivation) {
    out.println("process Activation");
}

public void process(OperationPayment operationPayment) {
    out.println("process Payment");
}

public void process(OperationSendEmail operationSendEmail) {
    out.println("process OperationSendEmail");
}        

}

Обработка каждой операции требует другой логики, поэтому я хочу иметь три разных метода, по одному для каждой операции.

Конечно, этот код не компилируется. Я что-то упустил или это нельзя сделать таким образом?

Ответы [ 6 ]

5 голосов
/ 15 июня 2009

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

public class ProcessOperationService {

public void processOperation(Operation operation) {
    out.println("process Operation");
    if (operation instanceof OperationActivation)
        process((OperationActivation)operation);
    else if (operation instanceof OperationPayment)
        process((OperationPayment)operation);
    ...
}

public void process(OperationActivation operationActivation) {
    out.println("process Activation");
}
...
}

Было бы гораздо лучше, чтобы автоматический полиморфизм во время выполнения работал, выполняя действия, предложенные Брайаном Агнью, и создавая процесс как метод для каждого подтипа Operation.

4 голосов
/ 15 июня 2009

Разве ваши Operation* объекты не должны выполнять работу самостоятельно? Таким образом, вы можете написать (скажем)

for (Operation op : ops) {
   op.process();
}

Вы можете инкапсулировать логику для каждой конкретной операции в своем собственном классе, и таким образом все, что связано с OperationPayment, остается в классе OperationPayment. Вам не нужен класс Processor (и поэтому вам не нужно изменять класс Processor каждый раз, когда вы добавляете операцию)

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

1 голос
/ 15 июня 2009

Не будет ли здесь полезен шаблон Visitor?

Класс Operation может объявить метод accept, который принимает объект Visitor, а подклассы могут иметь реализацию:

public interface IOperationVisitor {
   public void visit (OperationActivation visited);
   public void visit (OperationPayment visited);
   public void visit (OperationSendEmail visited);
}

abstract class Operation {      
   public void accept(IOperationVisitor visitor)();
}

class OperationActivation extends Operation {
    public void accept(IOperationvisitor visitor) {
         visitor.visit(this);
    }
}

Аналогичным образом определите метод accept для классов OperationPayment и OperationSendEmail.

Теперь ваш класс может реализовать посетителя:

public class ProcessOperationService implements IOperationVisitor  {

     public void processOperation(Operation operation) {
         operation.accept(this);
     }

     public void visit (OperationActivation visited) {
        // Operation Activation specific implementation
     }

     public void visit (OperationPayment visited) {
        // OperationPayment  specific implementation
     }

      public void visit ((OperationSendEmail visited) {
        // (Operation SendEmail specific implementation
       }
  }
1 голос
/ 15 июня 2009

Итак, у вас есть абстрактный класс с именем ' Operation ', и он имеет 3 класса, расширяющих его. Не уверен, что это то, что вам нужно, но я бы подумал, что оно будет разработано примерно так:

Operation.java

public abstract class Operation {

    public abstract void process();

}

OperationActivation.java

public class OperationActivation extends Operation {

    public void process() {

        //Implement OperationActivation specific logic here

    }

}

OperationPayment.java

public class OperationPayment extends Operation {

    public void process() {

        //Implement OperationPayment specific logic here

    }

}

OperationSendEmail.java

public class OperationSendEmail extends Operation {

    public void process() {

        //Implement OperationSendEmail spepcific logic here

    }

}

ProcessOperationService.java

public class ProcessOperationService {

    public void processOperation(Operation operation) {

        out.println("process Operation");
        operation.process();

    }

}
1 голос
/ 15 июня 2009

Проблема с кодом заключается в том, что любой объект, который соответствует одному из методов процесса (Operation *), также будет соответствовать методу process (Operation). Поскольку есть два метода, которые можно использовать, компилятор предупреждает вас о неоднозначной ситуации.

Если вы действительно хотите / нуждаетесь в приведенном выше коде, я бы предложил реализовать методы process (Operation *) и изменить метод process (Operation) так, чтобы он назывался processCommon. (Операция). Затем первое, что делает каждый процесс (Operation *), это вызывает processCommon.

Кроме того, вы можете кодировать в точности так, как сказал Ави, используя экземпляр сравнения.

Ни один из них не идеален, но он достигнет того, что вы хотите.

1 голос
/ 15 июня 2009

Предположение: операция * объекты являются подклассами операции

Если метод processOperation (Operation) не выполняет некоторые общие функции, вы можете просто удалить его и предоставить методы process (Operation).

Шаблон команды ( JavaWorld Explanation ) может быть полезен, но сложно точно определить, какие свойства вы хотите получить из своего вопроса.

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