发送Object类型的对象而不是String - Polymorphism

时间:2011-02-27 16:49:34

标签: java interface casting polymorphism

我有一个现有的方法,如下所示:

  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进行转换来使用它。

这是正确的做法还是有更好的方法。做上述事情有危险吗?

PS。我必须使用上面的转换方法作为im使用JDK1.4

由于

更新

我无法修改parseMessage方法。它内部有一个调用,它为每个相关的解析器调用parse()方法。

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

上面显示的解析器引用是一个实现接口“Parser”的对象。我正在介绍的新解析器遵循这种结构,它还实现了“Parser”接口。唯一的修改(即对MessageObject的转换)在新的解析器中。

我无法更改现有的parseMethod,因为这将需要更改实现“Parser”界面的所有现有解析器。我想避免根据消息类型调用特定的解析器。

如果我使用我建议的方法,现有的解析器仍将收到String消息,而新的解析器将收到一个String,但它需要先将它强制转换回MessageObject。

修改

我必须根据谢尔盖的评论对此进行测试。

界面

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


    package com;

MessageA Parser

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

MessageB Parser

    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 个答案:

答案 0 :(得分:2)

您可以重载parseMessage,因此它有两种形式:一种采用String参数,另一种采用MessageObject参数。

答案 1 :(得分:2)

MessageObject类不是String子类,因此您无法传递它而不是String。而且你不能将String子类化,因为它被声明为final。所以你无法将MessageObject(无论是什么)传递给现有的parseMessage()函数。

  

我无法更改现有的parseMethod   因为这将需要改变所有   实现的现有解析器   “Parser”界面。我想要   避免必须调用特定的解析器   取决于消息类型。

Parser.parse()的签名究竟是什么?如果它是parse(String message),那么除了字符串之外你不可能传递任何东西。

但是,如果这是您不想修改现有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接口,该接口应该扩展旧的Parser。

答案 2 :(得分:1)

我认为这里有一些更清洁的解决方案。第一个是你可以扩展实现parseMessage的类并添加一个额外的方法。

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

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

或者,您可以装饰包含parseMessage的类。但是,我假设你可以修改包含parseMessage的类,因为你说你想把它放在那里。

答案 3 :(得分:1)

如果你要解析越来越多的东西,而不是重载parse方法,你应该引入一个接口:

public interface Parseable {
    public String getMessage();
}

MessageObject将实现Parseable,您可以为String对象使用匿名适配器类:

final String m = "theMessageToParse";
parseMessage(new Parseable() {
    public String getMessage() {
        return m;
    }
});