Отправка в объекте типа Object вместо String - Полиморфизм - PullRequest
1 голос
/ 27 февраля 2011

У меня есть существующий метод, который выглядит следующим образом:

  public void parseMessage(String message){
    ...
    ...
    ...
  }

, и метод вызывается путем вызова его, как показано ниже

 String message;
 parseMessage(message);

Мне нужно изменить его для негообработать новый тип сообщения.Синтаксический анализатор для нового типа сообщения, вызываемого из метода parseMessage, сначала ожидает некоторые свойства, прежде чем сможет проанализировать сообщение.Я собираюсь передать сообщение как объект, который выглядит следующим образом:

public class MessageObject{
  private String message;
  private String namespace;
  private String xmlVersion;
}

Затем я могу вызвать существующий метод как

 Object messageObject;
 parseMessage(messageObject);

. Затем я могу использовать его нас другой стороны, приведя его как (MessageObject) messageObject.

Это правильный способ сделать это или есть лучший подход.Есть ли какие-либо опасности для выполнения вышеизложенного?

пс.Я должен использовать вышеупомянутый подход приведения, поскольку я использую JDK1.4

Спасибо

Обновление

Я не могу изменить метод parseMessage.Внутри него есть вызов, который вызывает метод parse () для каждого соответствующего анализатора.

 public void parseMessage(String message){
    ...
    ...
    parser.parse(message)
  }

Ссылка парсера, показанная выше, является объектом, который реализует интерфейс "Парсер".Новый парсер, который я представляю, следует этой структуре, а также реализует интерфейс "Parser".Единственные модификации (т.е. приведение к MessageObject) находятся в новом парсере.

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

Если я использую подход, который я предлагаю, существующие парсеры все равно получат сообщение String, в то время как новый парсер получит String, но сначала ему нужно будет привести его к MessageObject.

Редактировать

Я должен был проверить это, основываясь на комментариях Сергея.

Интерфейс

    package com;
    public interface Parser{
        public void parse(String message);
    }


    package com;

Парсер MessageA

    public class MessageAParser implements Parser{
        public void parse(String message){
            System.out.println("Parsing A");
        }
    }

Парсер MessageB

    package com;

    public class MessageAParser implements Parser{
        public void parse(String message){
            System.out.println("Parsing A");
        }
    }

Парсер MessageC (ожидается объект)

    package com;
    public class MessageCParser implements Parser{
        public void parse(Object message){
            MessageObject mobject = (MessageObject)message; 
            System.out.println("Parsing C" + mobject.getMessage());
        }

        public void parse(String m){}
    }

Диспетчер синтаксических анализаторов, который вызывает соответствующий анализатор.

    package com;

    import java.util.HashMap;

    public class ParserManager{

        public ParserManager() {
            prepare();
        }

        HashMap parsers = new HashMap();


        public void prepare(){

            parsers.put("A",new MessageAParser());
            parsers.put("B",new MessageBParser());
            parsers.put("C",new MessageCParser());
        }

        public void parseMessage(String msgType, String message){
            ((Parser)parsers.get(msgType)).parse(message);
        }
    }


    package com;

Контроллер.

    public class ControlClass{

        public static void main(String[] args){

            ParserManager pManager = new ParserManager();

            //Parse A
            pManager.parseMessage("A","ATEXT TO PARSE");

            //Parse B
            pManager.parseMessage("B","BTEXT TO PARSE");

            //Parse C
            Object mobject = new MessageObject();
            pManager.parseMessage("C",(String)mobject);
        }
    }

Когда я запускаю вышеупомянутый класс Controller, он выводит текст для первых двух сообщений, но завершает работу с третьим.

Parsing A
Parsing B
java.lang.ClassCastException
    at com.ControlClass.main(ControlClass.java:17)
Exception in thread "main" 

Ответы [ 4 ]

2 голосов
/ 27 февраля 2011

Класс MessageObject не является подклассом String, поэтому вы не можете передать его вместо String. И вы не можете создать подкласс String, поскольку он объявлен как final. Поэтому вы не можете передать MessageObject (что бы это ни было) в существующую функцию parseMessage ().

я не могу изменить существующий метод parseMethod так как это потребует изменения всех существующие парсеры, которые реализуют интерфейс "Parser". я бы хотел избежать вызова конкретного анализатора в зависимости от типа сообщения.

Что именно является подписью Parser.parse ()? Если это parse(String message), то вы не можете передать туда ничего, кроме String.

Однако, если это единственная причина, по которой вы не хотите изменять существующий parseMessage (), существует обходной путь:

public void parseMessage(Object message) { // changed to Object
  ...
  ...
  if (message instanceof String)
    parser.parse((String) message);
  else {
    if (message instanceof MessageObject) {
      if (!(parser instanceof MessageObjectParser)) {
        throw new IllegalArgumentException(
          "A MessageObject is passed, but not supported by the parser");
      }
      ((MessageObjectParser) parser).parse((MessageObject) message);
    } else {
      throw new IllegalArgumentException(
        "Messages of type " + parser.getClass() + " aren't supported");
    }
  }
}

Это немного уродливо, но, вероятно, сработает. Теперь у вас есть только новые парсеры, реализующие новый интерфейс MessageObjectParser, который должен расширять старый парсер.

2 голосов
/ 27 февраля 2011

Вы можете перегрузить parseMessage, чтобы он имел два варианта: один, принимающий аргумент String, и другой, принимающий аргумент MessageObject.

1 голос
/ 27 февраля 2011

Если у вас есть все больше и больше типов для анализа, вместо перегрузки метода синтаксического анализа вы должны ввести интерфейс:

public interface Parseable {
    public String getMessage();
}

MessageObject будет реализовывать Parseable, и вы можете использовать анонимный адаптеркласс для строковых объектов:

final String m = "theMessageToParse";
parseMessage(new Parseable() {
    public String getMessage() {
        return m;
    }
});
1 голос
/ 27 февраля 2011

Я думаю, что здесь есть пара более чистых решений.Во-первых, вы можете расширить класс, который реализует parseMessage, и добавить дополнительный метод.

public void parseMessage(MessageObject messageObject) {
  // Additional stuff here
  ...

  // Call through to original
  parseMessage(messageObject.message);
}

В качестве альтернативы, вы можете просто украсить класс, содержащий parseMessage.Тем не менее, я предполагаю, что вы можете изменить класс, содержащий parseMessage, так как вы говорите, что хотите в любом случае привести его туда.

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