在Object类型的对象中发送,而不是String - 多态性 [英] Sending in an object of type Object instead of String - Polymorphism
问题描述
我有一个现有的方法,如下所示:
public void parseMessage(String message){
...
...
...
}
字符串消息;
parseMessage(message);
我需要修改它来处理一种新类型的消息。从parseMessage方法调用的新类型消息的解析器在解析消息之前需要先获取一些属性。我想做的是将消息作为一个对象看起来像这样
public class MessageObject {
private字符串消息;
private String namespace;
private String xmlVersion;
}
然后我可以调用现有的方法
Object messageObject;
parseMessage(messageObject);
然后我可以通过将它转换为(MessageObject)messageObject来使用它。
这是正确的做法,或有一个更好的方法。有没有任何危险做上述?
ps。我必须使用JDK1.4使用上面的铸造方法im。
感谢
更新
我不能修改parseMessage方法。它在里面有一个调用,它为每个相关的解析器调用parse()方法。
public void parseMessage(String message){
...
...
parser.parse(message)
}
上面所示的解析器引用是一个实现接口解析器。我介绍的新解析器遵循此结构,它还实现了解析器接口。唯一的修改(即转换到MessageObject)在新的解析器中。
我无法更改现有的parseMethod,因为这将需要更改实现解析器接口的所有现有解析器。我想避免根据消息类型调用特定的解析器。
如果我使用我建议的方法,现有的解析器仍然会收到一个字符串消息,而新的解析器将收到一个字符串,但它需要将其转换回MessageObject第一。
编辑
我不得不根据Sergey的意见测试这个。
界面
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解析器
package com;
public class MessageAParser implements Parser {
public void parse(String message){
System.out.println(Parsing A); MessageC解析器(这期望一个对象))
$ b >
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){}
}
b $ b
解析器管理器调用相关解析器。
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))。
}
}
package com;
控制器。
public class ControlClass {
public static void main(String [] args){
ParserManager pManager = new ParserManager();
// Parse A
pManager.parseMessage(A,ATEXT TO PARSE);
//解析B
pManager.parseMessage(B,BTEXT TO PARSE);
//解析C
Object mobject = new MessageObject();
pManager.parseMessage(C,(String)mobject);
}
}
当我运行上面的Controller类时,对于前两个消息,但对于第三个消息失败。
解析A
解析B
java.lang.ClassCastException
at com.ControlClass。 main(ControlClass.java:17)
线程main中的异常
解决方案 MessageObject类不是String子类,因此您不能传递它而不是String。并且你不能继承String,因为它被声明为final。所以没有办法你可以传递MessageObject(无论是什么)到现有的parseMessage()函数。
parseMethod
因为这将需要更改所有的
现有的解析器实现
解析器接口。我想要
避免根据消息类型调用特定的解析器
。
签名的Parser.parse()?如果它 parse(String message)
,那么你不能传递任何其他的字符串。
但是,如果这是你不想修改现有parseMessage()的唯一原因,那么有一个解决方法:
public void parseMessage(Object message){//改为Object
...
...
if(message instanceof String)
parser.parse((String)message) ;
else {
if(message instanceof MessageObject){
if(!(parser instanceof MessageObjectParser)){
throw new IllegalArgumentException(
MessageObject is passed,不支持解析器);
}
((MessageObjectParser)parser).parse((MessageObject)message);
} else {
throw new IllegalArgumentException(
不支持类型为+ parser.getClass()+的消息);
}
}
}
这有点丑陋,可能会工作。现在你只有你的新解析器实现新的MessageObjectParser接口,它应该扩展旧的解析器。
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"
解决方案 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.
这篇关于在Object类型的对象中发送,而不是String - 多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!