发送Object类型的对象而不是String – 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" 

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接口,该接口应该扩展旧的Parser。

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

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

 public void parseMessage(MessageObject messageObject) { // Additional stuff here ... // Call through to original parseMessage(messageObject.message); } 

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

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

 public interface Parseable { public String getMessage(); } 

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

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