Skip to content

Instantly share code, notes, and snippets.

@colinsullivan
Created December 8, 2011 08:59
Show Gist options
  • Save colinsullivan/1446508 to your computer and use it in GitHub Desktop.
Save colinsullivan/1446508 to your computer and use it in GitHub Desktop.
Trying to get a simple event handler interface in ChucK
/**
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 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