D - Patterns Observable
- Don Stewart (26/26) May 17 2002 I'm looking for a couple of things. Suggestions only mind but here goes.
- Patrick Down (78/82) May 18 2002 I think the solution to this type of problem is
- Don Stewart (11/93) May 17 2002 Yes exactly but I was thinking along the lines of the compiler inserting...
- Don Stewart (9/122) May 24 2002 I managed to find the code inlusion in another language called Sather.
- Sean L. Palmer (5/9) May 24 2002 I find myself wanting this type of functionality all the time. But I'm ...
- Don Stewart (7/17) May 24 2002 Exactly.
I'm looking for a couple of things. Suggestions only mind but here goes. I've found the observer pattern very useful in JAVA, with one caveat, the fact they made it an object that you have to inherit from. Bang goes your single inheritence. But to define it as an interface would mean implementing the behaviour each time. Yuck. <Puts on fireproof suit :o) > So whats the option. Is there some way in the language we can have something like class Observeable { notifyObservers(); } class B encaptulates Observeable { } where what would actually happen is that the compiler would generate class B { notifyObservers(); } So the funtionality of Oberver is encapsulated in B. In this way Observer would work. Overloading of the method is not allowed. Although maybe you could sub-class Observable itself. Then again maybe not. Now I know this looks alot like multiple inheritence, but if the compiler barfed if the user added a function notifyObservers() to class B then it would overcome the issue. Multiple inheritence is difficult and prone to error, but single inheritence is very restrictive. Don
May 17 2002
"Don Stewart" <donald.m.stewart btinternet.com> wrote in news:ac5r2l$1s5a$1 digitaldaemon.com:I've found the observer pattern very useful in JAVA, with one caveat, the fact they made it an object that you have to inherit from. Bang goes your single inheritence. But to define it as an interface would mean implementing the behaviour each time. Yuck.I think the solution to this type of problem is mixins. A mixin is a piece of data and functionality that can be aggregated into another class. I like to explain these types of with concrete examples. Lets take the observer pattern mentioned above. Lets also say for the moment that D has a preprocessor like C does. I'm not saying that D should have a preprocessor, I'm just using it as a device to explain the idea I'm getting to below. The observer interfaces... interface IObserver { void update(IObserver from, Object obj); } interface IObservable { void addObserver(IObserver obs); void deleteObserver(IObserver obs); void deleteObservers(); int countObservers(); boolean hasChanged(); void notifyObservers(); void notifyObservers(Object obj); } So you want class Foo to be observable. That means that you must specify IObservable as an interface Foo implements. But then you have to actually implement all the functionality that is in IObservable. As noted this is rather tedious to do for every class that you want to be Observable. But suppose you made a proprocessor macro. #define IMPLEMENTS_OBSERVABLE \ IObserver[] observers; \ bit changed; \ void addObserver(IObserver obs) \ { \ observers ~= obj; \ } \ void notifyObservers() \ { \ for(int i = 0; i < observers.length; ++i) \ observers[i].update(this,null); \ } I'm not going to create the whole macro but you get the idea. So now you can make Foo line this... class Foo : BaseClass, IObservable { IMPLEMENTS_OBSERVABLE } This works but it uses a macro preprocessor that D has doesn't have for various good reasons. So I might suggest something like this. struct Observable { IObserver[] observers; bit changed=false; void addObserver(IObserver obs) { observers ~= obj; } void notifyObservers() { for(int i = 0; i < observers.length; ++i) observers[i].update(this,null); } // Other functions } class Foo : BaseClass, IObservable { mixin Observable a; } This is better than the macro. The Observable struct can be syntax checked at the point it's defined. All the functions in Observable could automatically generated in Foo be generating functions like... void addObserver(IObserver obs) { a.addObserver(obs); }
May 18 2002
Yes exactly but I was thinking along the lines of the compiler inserting the binary code of the Observable class in the, implementing object (okay so it's not really implementing because it's not an interface it's a compiled mixin object) rather than using macros. So in effect there is a language keyword that supports the observable macro. Now I agree we cannot add keywords for too many things otherwise there is a keyword explosion. But some the Gamma patterns are used frequently these days and it would be nice for them to be language contsructs. I was glad when I switched to JAVA and dumped macro's, hopefully, for good. "Patrick Down" <pat codemoon.com> wrote in message news:Xns92128C2162F8Epatcodemooncom 63.105.9.61..."Don Stewart" <donald.m.stewart btinternet.com> wrote in news:ac5r2l$1s5a$1 digitaldaemon.com:I've found the observer pattern very useful in JAVA, with one caveat, the fact they made it an object that you have to inherit from. Bang goes your single inheritence. But to define it as an interface would mean implementing the behaviour each time. Yuck.I think the solution to this type of problem is mixins. A mixin is a piece of data and functionality that can be aggregated into another class. I like to explain these types of with concrete examples. Lets take the observer pattern mentioned above. Lets also say for the moment that D has a preprocessor like C does. I'm not saying that D should have a preprocessor, I'm just using it as a device to explain the idea I'm getting to below. The observer interfaces... interface IObserver { void update(IObserver from, Object obj); } interface IObservable { void addObserver(IObserver obs); void deleteObserver(IObserver obs); void deleteObservers(); int countObservers(); boolean hasChanged(); void notifyObservers(); void notifyObservers(Object obj); } So you want class Foo to be observable. That means that you must specify IObservable as an interface Foo implements. But then you have to actually implement all the functionality that is in IObservable. As noted this is rather tedious to do for every class that you want to be Observable. But suppose you made a proprocessor macro. #define IMPLEMENTS_OBSERVABLE \ IObserver[] observers; \ bit changed; \ void addObserver(IObserver obs) \ { \ observers ~= obj; \ } \ void notifyObservers() \ { \ for(int i = 0; i < observers.length; ++i) \ observers[i].update(this,null); \ } I'm not going to create the whole macro but you get the idea. So now you can make Foo line this... class Foo : BaseClass, IObservable { IMPLEMENTS_OBSERVABLE } This works but it uses a macro preprocessor that D has doesn't have for various good reasons. So I might suggest something like this. struct Observable { IObserver[] observers; bit changed=false; void addObserver(IObserver obs) { observers ~= obj; } void notifyObservers() { for(int i = 0; i < observers.length; ++i) observers[i].update(this,null); } // Other functions } class Foo : BaseClass, IObservable { mixin Observable a; } This is better than the macro. The Observable struct can be syntax checked at the point it's defined. All the functions in Observable could automatically generated in Foo be generating functions like... void addObserver(IObserver obs) { a.addObserver(obs); }
May 17 2002
I managed to find the code inlusion in another language called Sather. Sather defines a keyword called partial. To quote "Partial classes define code that does not have corresponding objects or type, and may be included by other classes to obtain implementation. "Don Stewart" <donald.m.stewart btinternet.com> wrote in message news:ac698h$280c$1 digitaldaemon.com...Yes exactly but I was thinking along the lines of the compiler insertingthebinary code of the Observable class in the, implementing object (okay so it's not really implementing because it's not an interface it's a compiled mixin object) rather than using macros. So in effect there is a language keyword that supports the observable macro. Now I agree we cannot add keywords for too many things otherwise there is a keyword explosion. But some the Gamma patterns are used frequently these days and it would benicefor them to be language contsructs. I was glad when I switched to JAVA and dumped macro's, hopefully, forgood."Patrick Down" <pat codemoon.com> wrote in message news:Xns92128C2162F8Epatcodemooncom 63.105.9.61..."Don Stewart" <donald.m.stewart btinternet.com> wrote in news:ac5r2l$1s5a$1 digitaldaemon.com:I've found the observer pattern very useful in JAVA, with one caveat, the fact they made it an object that you have to inherit from. Bang goes your single inheritence. But to define it as an interface would mean implementing the behaviour each time. Yuck.I think the solution to this type of problem is mixins. A mixin is a piece of data and functionality that can be aggregated into another class. I like to explain these types of with concrete examples. Lets take the observer pattern mentioned above. Lets also say for the moment that D has a preprocessor like C does. I'm not saying that D should have a preprocessor, I'm just using it as a device to explain the idea I'm getting to below. The observer interfaces... interface IObserver { void update(IObserver from, Object obj); } interface IObservable { void addObserver(IObserver obs); void deleteObserver(IObserver obs); void deleteObservers(); int countObservers(); boolean hasChanged(); void notifyObservers(); void notifyObservers(Object obj); } So you want class Foo to be observable. That means that you must specify IObservable as an interface Foo implements. But then you have to actually implement all the functionality that is in IObservable. As noted this is rather tedious to do for every class that you want to be Observable. But suppose you made a proprocessor macro. #define IMPLEMENTS_OBSERVABLE \ IObserver[] observers; \ bit changed; \ void addObserver(IObserver obs) \ { \ observers ~= obj; \ } \ void notifyObservers() \ { \ for(int i = 0; i < observers.length; ++i) \ observers[i].update(this,null); \ } I'm not going to create the whole macro but you get the idea. So now you can make Foo line this... class Foo : BaseClass, IObservable { IMPLEMENTS_OBSERVABLE } This works but it uses a macro preprocessor that D has doesn't have for various good reasons. So I might suggest something like this. struct Observable { IObserver[] observers; bit changed=false; void addObserver(IObserver obs) { observers ~= obj; } void notifyObservers() { for(int i = 0; i < observers.length; ++i) observers[i].update(this,null); } // Other functions } class Foo : BaseClass, IObservable { mixin Observable a; } This is better than the macro. The Observable struct can be syntax checked at the point it's defined. All the functions in Observable could automatically generated in Foo be generating functions like... void addObserver(IObserver obs) { a.addObserver(obs); }
May 24 2002
"Don Stewart" <donald genient.com> wrote in message news:aclmtj$jq5$1 digitaldaemon.com...I managed to find the code inlusion in another language called Sather. Sather defines a keyword called partial. To quote "Partial classes define code that does not have corresponding objects or type, and may be included by other classes to obtain implementation.I find myself wanting this type of functionality all the time. But I'm not sure that there isn't a better way. Sean
May 24 2002
Exactly. I'm not sugesting this is the way. But a way would be very very useful. Don "Sean L. Palmer" <seanpalmer earthlink.net> wrote in message news:aclsmq$peh$1 digitaldaemon.com..."Don Stewart" <donald genient.com> wrote in message news:aclmtj$jq5$1 digitaldaemon.com...notI managed to find the code inlusion in another language called Sather. Sather defines a keyword called partial. To quote "Partial classes define code that does not have corresponding objects or type, and may be included by other classes to obtain implementation.I find myself wanting this type of functionality all the time. But I'msure that there isn't a better way. Sean
May 24 2002