Proxy objects and controlling/monitoring access

Reiner Pope some at address.com
Fri Aug 17 16:21:32 PDT 2007


Bill Baxter wrote:
> This is something I've been thinking about lately.
> Here's something I think is maybe a sort of language challenge akin to 
> Andrei's "identity" template.  It's something that if you can do, opens 
> up a lot of possibilities, even though it may not be that interesting by 
> itself.
> 
> Ok, so the challenge is, can you make a wrapper around a value that 
> behaves identically to the value BUT also allows you to monitor each 
> access?  The uses for this are many.  In particular observer patterns 
> and the like often involve getting notifications when things change.
> 
> One thing making me thing about this is the enthough.traits framework in 
> Python that I've been looking at lately.  It's a very powerful paradigm 
> for linking components together.  Basically when you use traits, instead 
> of creating class memebers in the normal way you create them using 
> something akin to 'my_int = new traits.Int'.  From there my_int 
> basically looks exactly like a regular int to all users, the twist being 
> that you can easily get a notification every time my_int changes.
> 
> So can we do this in D?  I guess you might call this "identity with 
> notifications"
> 
> We can certainly do a lot of it using operator overloads.  But we can't 
> do everything.  For instance, if you want to wrap a struct there's no 
> way to emulate getting and setting of the struct's members without 
> writing a specific wrapper that adds property get/set methods for each 
> member of the wrapped struct.
> 
> 
> --bb

I've written code which wraps a value in a class which derives from a 
given interface. The interface is implemented by calling the value's 
fields.  See the unit test of the attached mixininterface.d for 
examples. In fact, the code isn't so messy, but it uses my own 
collection of CTFE utils in my_metastrings.

I don't imagine it would be too hard to adapt my code to generate the 
wrapper you want.

There are two behavioural differences, though:

1.
The generated class will have reference semantics, whether the backing 
type is a value or a reference. This is partly a consequence of wrapping 
it in an interface, but if I was trying to create the wrapper you 
wanted, it would still be a problem. One solution would simply be to 
check whether the type is a value or a reference type. If it's a value 
type, implement the wrapper as a struct, if it's a reference, implement 
the wrapper as a class. The alternative (but currently impossible) would 
be to overload the class's opAssign for itself, emulating value semantics.

2.
Casting doesn't work properly. You don't retain the implementation's 
position in the inheritance tree, so you can't cast back to it, etc.


    -- Reiner

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: my_metastrings.d
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20070818/44fec9c8/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: mixininterface.d
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20070818/44fec9c8/attachment-0001.ksh>


More information about the Digitalmars-d mailing list