View previous topic :: View next topic |
Author |
Message |
csauls
Joined: 27 Mar 2004 Posts: 278
|
Posted: Mon May 17, 2004 9:17 pm Post subject: Events |
|
|
One of the issues from the beginning was what to do about OGRE's event system. The way it is written in C++, there are event listeners which are inherited from to provide the appropriate capabilities. One uption which I think was mentioned, was to do something similar to what DWT is doing, by using sets of delegates to hook into an event system.
While that has its merits, I'd like to mention something new I've thought of now that mixins are becoming a reality. Consider the following hypothetical mouse listener with its single on-click event.
Code: |
interface iMouseListener
{
public void onMouseClick(MouseEvent);
}
template MouseListener() {
public void onMouseClick(MouseEvent event)
{
// do stuff
}
}
|
Now granted I don't know what a mouse listener might automatically do with a click, but the idea should come across. The issues I see with this myself have to do with code-bloat, wherein the mixin will cause (unless they are implemented differently than I think they are) each using class to have its own copy of all its code, meaning that if we have thirty mouse listeners, then there are thirty copies of onMouseClick. Yuck.
Overriding mixed-in methods wouldn't be a problem... just do something like:
Code: |
class MyListener : iMouseListener
{
mixin MouseListener baseMouseListener;
public:
void onMouseClick(MouseEvent event)
{
// do some custom stuff
// call original handler
baseMouseListener.onMouseClick(event);
}
}
|
_________________ Chris Nicholson-Sauls |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Tue May 18, 2004 1:17 am Post subject: Re: Events |
|
|
csauls wrote: | The issues I see with this myself have to do with code-bloat, wherein the mixin will cause (unless they are implemented differently than I think they are) each using class to have its own copy of all its code, meaning that if we have thirty mouse listeners, then there are thirty copies of onMouseClick. Yuck.
|
I think that it might not be a problem. The mixins are really templates and the normal templates at least only have one instanciation even if it's used more than once (as long as the template arguments the same). |
|
Back to top |
|
|
andy
Joined: 15 Mar 2004 Posts: 71
|
Posted: Tue May 18, 2004 12:31 pm Post subject: |
|
|
Delegates would probably result in a more straightforward interface, if only because small test applications can just throw function literals into listeners and let it fly.
Ogre uses listener interfaces because there really isn't a better way to do it in C++. (not without getting into boost or arcane template/macro magic)
I suppose that relatively complex listeners (over four methods or so) may be better implemented as interfaces. MouseListener and KeyListener are the only ones I can see offhand that are this complicated, so it may be worthwhile to implement them the same way as the others for consistency's sake.
If you're going to use interfaces, the other thing you could do is provide Adapter implementations that implement the interface with no-ops; client code can extend the Adapter and override what they want to override, or they can implement the interface. (this is how Java does a whole lot of things) _________________ "Complacency is a far more dangerous attitude than outrage." - Naomi Littlebear |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Tue May 18, 2004 2:53 pm Post subject: |
|
|
andy wrote: | If you're going to use interfaces, the other thing you could do is provide Adapter implementations that implement the interface with no-ops; client code can extend the Adapter and override what they want to override, or they can implement the interface. (this is how Java does a whole lot of things) |
This is of (almost) no use, since almost everything in OGRE inherits from something else. There's no room to use Adapters. |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Mon May 31, 2004 4:12 am Post subject: |
|
|
larsivi wrote: | andy wrote: | If you're going to use interfaces, the other thing you could do is provide Adapter implementations that implement the interface with no-ops; client code can extend the Adapter and override what they want to override, or they can implement the interface. (this is how Java does a whole lot of things) |
This is of (almost) no use, since almost everything in OGRE inherits from something else. There's no room to use Adapters. |
I just saw that many of the listeners in OGRE really ARE like adapters, even though they don't need to be. Most of them have empty implementations, meaning that Sinbad can make them become interfaces, thus removing many of the MI problems. (There still might be some issues when we come to the level where the interfaces are implemented, but it is then mixins probably step up to help.)
If we want adapters (to ease development for the application programmer), we can make them as mixins, doing something like this:
Code: |
class MyApp
: ListenerInterface
{
mixin ListenerAdapter;
...
}
|
|
|
Back to top |
|
|
csauls
Joined: 27 Mar 2004 Posts: 278
|
Posted: Thu Jun 17, 2004 2:45 pm Post subject: |
|
|
That system of interface + mixin looks to me like a good course to take. _________________ Chris Nicholson-Sauls |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Sun Sep 05, 2004 3:13 pm Post subject: |
|
|
After looking closer at the eventsystem, there seems to be a couple of hitches.
1. In the case where a Listener implementation need to satisfy several methods in the listener interface, a mixin become problematic. You either need a mixin per method, making it rather useless since the implementations are more like stubs anyway.
2. There is at least one paradigm problem with the EventMulticaster class, as it makes good use of MI from classes with a common superclass. Then it makes conversions around the block based on said superclasses (I think). Now, this is hopeless, because EventMulticaster is far from just an interface (although it's superclasses are), which again cause problems since the subclasses needs it as an interface.
The solution? Ditch the event system, and find something else. Maybe dcouple can be of use, or we'll make do with delegates. |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Thu Sep 09, 2004 2:44 am Post subject: |
|
|
When I get back on track, I think I'll use the Dispatcher class seen elsewhere. It's easier to convert that to interfaces later as opposed to starting with them, if they turn out to be a must have. I think delegates combined with interfaces might turn out to be the best solution in the end. |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Thu Sep 16, 2004 2:23 pm Post subject: |
|
|
Changed my mind again. I'll keep using interfaces and deal with EventMulticaster when needed. |
|
Back to top |
|
|
larsivi Site Admin
Joined: 27 Mar 2004 Posts: 453 Location: Trondheim, Norway
|
Posted: Sat Jan 29, 2005 10:06 am Post subject: |
|
|
Ok, the interface + mixins approach works (no surprise) so I'll go for it. The only problem I can see, are in the cases (if any) where the implementation provided by a mixin is fairly complex and the subclass want's to reimplement and call the method in the superclass. This won't work as the implementation isn't in the superclass but in the class where the reimplementation is to take place. Maybe the problem can be aliased away? If that's the case, then I believe the problem is uncommon enough to not worry. |
|
Back to top |
|
|
csauls
Joined: 27 Mar 2004 Posts: 278
|
Posted: Sat Jan 29, 2005 2:29 pm Post subject: |
|
|
I think alias might do the trick... consider:
Code: |
// the mixin
public template Foo() {
public int method() {
// ...
}
public int another() {
// ...
}
}
// the implementor that wants to override
public class Bar {
// the use of an id is the key!
mixin Foo!() _foo;
// override 'method'
public int method() {
// ...
return _foo.method();
}
// just use alias for the method we don't override
alias _foo.another another;
}
|
Its a convention, not some pre-rendered syntax (which would be nice... maybe the 'override' keyword could be double-purposed? nah) but it should work. Granted, I didn't actually test it.. maybe I will when I get off work tonight. _________________ Chris Nicholson-Sauls |
|
Back to top |
|
|
|