One of the great things about Objective-C in MacOS is its dynamic messaging and delegation capabilities. Any object can delegate its messages to any other object. Java on the other hand is very strongly typed to detect and avoid problems at runtime.
I was thinking, if it would be possible to implement something like a dynamic messaging system in Java where any message can be posted to any object at runtime and if that object wants, it can optionally pre-process it, delegate it, or post process it. So, I made an abstract class called MessageDelegate and any class that implements it can receive, process and/or delegate messages.
Any object can register itself as a delegate of another object and that object would not have to know about it. Any object can choose not to implement pre or post processing, in which case the chain would continue. Any if one object has actually dealt with a particular message and wants to stop further processing, it can indicate with a return type.
This allows for a nice lazy programming style in java. However, there is a dark side to it as well. The problems include:
I was thinking, if it would be possible to implement something like a dynamic messaging system in Java where any message can be posted to any object at runtime and if that object wants, it can optionally pre-process it, delegate it, or post process it. So, I made an abstract class called MessageDelegate and any class that implements it can receive, process and/or delegate messages.
Any object can register itself as a delegate of another object and that object would not have to know about it. Any object can choose not to implement pre or post processing, in which case the chain would continue. Any if one object has actually dealt with a particular message and wants to stop further processing, it can indicate with a return type.
This allows for a nice lazy programming style in java. However, there is a dark side to it as well. The problems include:
- Not very flexible because most classes one writes are already extended from some interface or the other.
- Cyclic messaging infinite loops.
- Runtime exceptions. I've dealt with it by making sure messages are only string maps.
I've put up the classes on GitHub here. But you can see the following code on how it might be used in your code. Note that its not thread safe yet. If anyone wants to improve it, feel free to make your own fork and push any changes back to me :)
Next time maybe dynamic messaging in C++. I think C++ (much closer to Objective-C is much better suited for this kind of thing with void pointers and easy casting. Much riskier at runtime as well.
Next time maybe dynamic messaging in C++. I think C++ (much closer to Objective-C is much better suited for this kind of thing with void pointers and easy casting. Much riskier at runtime as well.
package com.fahdrafi.messagetest;
import com.fahdrafi.Messaging.Message;
import com.fahdrafi.Messaging.MessageDelegate;
public class DelegationTest extends MessageDelegate {
private String name = new String("unassigned");
// Optionally implement pre-processing method
public boolean PreProcess(Message msg) {
// first check to see if the message type is something you want to process
if (!msg.get(Message.MSG_TYPE).equals("PrintAction")) return false;
// do any processing you want here
//
//
//
System.out.println(name + " pre-processing: " + msg.get("PrintMessage"));
// return true if you have processed it and do not want further processing
// return false if you have not processed it
return false;
}
// similar post-processing after delegation
public boolean PostProcess(Message msg) {
if (!msg.get(Message.MSG_TYPE).equals("PrintAction")) return false;
System.out.println(name + " post-processing: " + msg.get("PrintMessage"));
return false;
}
DelegationTest(String newName) {
this.name = newName;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// Create any objects
DelegationTest o1 = new DelegationTest("Object 1");
DelegationTest o2 = new DelegationTest("Object 2");
DelegationTest o3 = new DelegationTest("Object 3");
DelegationTest o4 = new DelegationTest("Object 4");
// Add delegation to them
o1.AddDelegate(o2);
o2.AddDelegate(o3);
o3.AddDelegate(o4);
// Make a new message (its essentially a hashmap which returns "" if nothing is assigned to a key)
Message m = new Message("PrintAction");
m.put("PrintMessage","Hello Messaging!");
// Delegate(message) or Post(message) (Post only delegates and does not pre/post process messages
o1.Delegate(m);
}
}