问题
I've an existing method which looks like this:
public void parseMessage(String message){
...
...
...
}
and the method is called by calling it as shown below
String message;
parseMessage(message);
I need to modify it for it to process a new type of message. The parser for the new type of message which is called from the parseMessage method expects some properties first before it can parse the message. What i am thinking of doing is passing the message as an object that looks like this
public class MessageObject{
private String message;
private String namespace;
private String xmlVersion;
}
I can then call the existing method as
Object messageObject;
parseMessage(messageObject);
I can then use it on the other side by casting it as (MessageObject)messageObject.
Is this the correct way of doing it or is there a better approach. Are there any dangers to doing the above?
ps. i have to use the above casting approach as im using JDK1.4
Thanks
Update
I cant modify the parseMessage method. It has a call inside it which calls the parse() method for each relevant parser.
public void parseMessage(String message){
...
...
parser.parse(message)
}
The parser reference shown above is an object that implements an interface "Parser". The new parser i am introducing follows this structure and it also implements the "Parser" interface. The only modifications (i.e. the casting to MessageObject) are in the new parser.
i cant change the existing parseMethod as that will require changing all of the existing parsers that implement the "Parser" interface. I want to avoid having to call a specific parser depending on message type.
If i use the approach i am suggesting, existing parsers will still recieve a String message while the new parser will recieve a String but it will need to cast it back to MessageObject first.
Edit
I have had to test this based on Sergey's comments.
The Interface
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 parser (This expects an object)
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){}
}
The parser manager that calls the relevant parser.
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;
The controller.
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);
}
}
When i run the above Controller class it outputs the text for the first two messages but fails for the third one.
Parsing A
Parsing B
java.lang.ClassCastException
at com.ControlClass.main(ControlClass.java:17)
Exception in thread "main"
回答1:
The MessageObject class is not a String subclass, so you can't pass it instead of String. And you can't subclass String since it's declared as final. So there is no way you can pass a MessageObject (whatever that is) to the existing parseMessage() function.
i cant change the existing parseMethod as that will require changing all of the existing parsers that implement the "Parser" interface. I want to avoid having to call a specific parser depending on message type.
What exactly is the signature of the Parser.parse()? If it's parse(String message)
, then you can't possibly pass there anything else than a String.
However, if that's the only reason you don't want to modify the existing parseMessage(), then there is a workaround:
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");
}
}
}
It's a bit ugly, but will probably work. Now you only have your new parsers implement the new MessageObjectParser interface, which should extend the old Parser.
回答2:
You can overload parseMessage so it comes in two flavors: one that takes a String argument and one that takes a MessageObject argument.
回答3:
I think there a couple of cleaner solutions here. The first is that you could extend the class that implements parseMessage and add an additional method.
public void parseMessage(MessageObject messageObject) {
// Additional stuff here
...
// Call through to original
parseMessage(messageObject.message);
}
Alternatively, you could just decorate the class that contains parseMessage. However, I am assuming that you can modify the class that contains parseMessage since you say you want to cast it in there anyway.
回答4:
If you have more and more types of things to parse, instead of overloading the parse method, you should introduce an interface :
public interface Parseable {
public String getMessage();
}
The MessageObject would implement Parseable, and you could use an anonymous adapter class for String objects :
final String m = "theMessageToParse";
parseMessage(new Parseable() {
public String getMessage() {
return m;
}
});
来源:https://stackoverflow.com/questions/5134462/sending-in-an-object-of-type-object-instead-of-string-polymorphism