www.digitalmars.com         C & C++   DMDScript  

D - Patterns Observable

reply "Don Stewart" <donald.m.stewart btinternet.com> writes:
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
parent reply Patrick Down <pat codemoon.com> writes:
"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
parent reply "Don Stewart" <donald.m.stewart btinternet.com> writes:
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
parent reply "Don Stewart" <donald genient.com> writes:
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 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 24 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
"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
parent "Don Stewart" <donald.m.stewart btinternet.com> writes:
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...
 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