Created
December 8, 2011 08:59
-
-
Save colinsullivan/1446508 to your computer and use it in GitHub Desktop.
Trying to get a simple event handler interface in ChucK
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
My goal is the interface at the bottom of the file: | |
MyWatcher c; | |
HappyEvent a; | |
spork ~ c.watch(a); | |
When this `watch` method is called, the `MyWatcher` instance `c` should handle the call to | |
a.broadcast(); | |
by calling its `callback` method which takes a `HappyEvent` object as a parameter. | |
Unfortunately this doesn't work because when the `HappyEvent` instance is being sent into | |
the `watch` method, it is cast to an `Event` type, which is then used to determine which | |
polymorphic callback method to use. This is proven with the commented out second | |
callback method in `EventCallbacks`, which yields the same result when un-commented. | |
To run: | |
chuck EventHandlerTest.ck | |
Output: | |
MyWatcher._eventCallbacks.callback(HappyEvent) should be called in one second: | |
EventCallbacks._eventCallbacks.callback(Event) | |
**/ | |
/** | |
* @class Base abstract functor class. | |
* | |
* This should be used for creating callbacks for | |
* events. Ideally, subclasses of this would | |
* be able to override the `callback` method with | |
* different `Event` types. | |
**/ | |
class EventCallbacks { | |
fun void callback(Event a) { | |
<<< "\t", "EventCallbacks._eventCallbacks.callback(Event)" >>>; | |
} | |
/*fun void callback(HappyEvent a) { | |
<<< "MyWatcher._eventCallbacks.callback(HappyEvent)" >>>; | |
}*/ | |
} | |
/** | |
* @class Base class for an event handler. | |
**/ | |
public class EventWatcher { | |
/** | |
* Pointer to new instance of `EventCallbacks` | |
* (or subclass). Subclasses should instantiate proper | |
* type. | |
**/ | |
new EventCallbacks @=> EventCallbacks @ _eventCallbacks; | |
fun void watch(Event a) { | |
a => now; // When a fires | |
// Handle event | |
spork ~ _eventCallbacks.callback(a); //react | |
// Handle event again next time | |
watch(a); | |
} | |
} | |
/** | |
* @class Subclass for example. | |
**/ | |
class MyWatcher extends EventWatcher { | |
/** | |
* @class Our own event callbacks. | |
* Overloaded `callback` method is used for | |
* different types of events. | |
**/ | |
class MyCallbacks extends EventCallbacks { | |
fun void callback(HappyEvent a) { | |
<<< "MyWatcher._eventCallbacks.callback(HappyEvent)" >>>; | |
} | |
} | |
new MyCallbacks @=> _eventCallbacks; | |
} | |
/** | |
* @class `Event` subclass for example. | |
**/ | |
class HappyEvent extends Event { | |
} | |
MyWatcher c; | |
HappyEvent a; | |
spork ~ c.watch(a); | |
<<< "\n", "MyWatcher._eventCallbacks.callback(HappyEvent) should be called in one second:" >>>; | |
1::second => now; | |
a.broadcast(); | |
1::second => now; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This attempt works better than if statements, but we're still | |
not taking advantage of polymorphism for different event | |
callbacks. It would be nice to have a single function | |
object with multiple polymorphic `call` methods to | |
handle different types of events. | |
*/ | |
/** | |
* Event callback functor class. | |
**/ | |
class BaseEventCallback { | |
fun void call(BaseEvent e) { | |
} | |
} | |
/** | |
* Base event class. | |
**/ | |
class BaseEvent extends Event { | |
/** | |
* Bind a callback to this event. | |
**/ | |
fun void bind(BaseEventCallback cb) { | |
this => now; // When event happens | |
cb.call(this); // Fire callback | |
bind(cb); // Wait for next time | |
} | |
} | |
/** | |
* @class Base class for an event handler. | |
**/ | |
public class EventWatcher { | |
} | |
/** | |
* @class `BaseEvent` subclass for example. | |
**/ | |
class HappyEvent extends BaseEvent { | |
} | |
/** | |
* @class Subclass for example. | |
**/ | |
class MyWatcher extends EventWatcher { | |
class MyCallback extends BaseEventCallback { | |
fun void call(BaseEvent e) { | |
/** | |
* This is my primary issue with this approach, | |
* it would be nice not to have to cast the | |
* `Event` object. | |
**/ | |
e $ HappyEvent @=> HappyEvent @ e; | |
<<< "\t", "MyWatcher.happyCallback.call(BaseEvent)" >>>; | |
} | |
fun void call(HappyEvent e) { | |
/** | |
* It would be nice if this was called, but it isn't | |
* because the bind method is in the more general | |
* `BaseEvent` class. | |
**/ | |
<<< "\t", "MyWatcher.happyCallback.call(HappyEvent)" >>>; | |
} | |
} | |
MyCallback happyCallback; | |
} | |
MyWatcher c; | |
HappyEvent a; | |
spork ~ a.bind(c.happyCallback); | |
<<< "\n", "MyWatcher.happyCallback.callback(HappyEvent) should be called in one second:" >>>; | |
1::second => now; | |
a.broadcast(); | |
1::second => now; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment