Proxy objects and controlling/monitoring access
Reiner Pope
some at address.com
Fri Aug 17 18:42:19 PDT 2007
Reiner Pope wrote:
> 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
>
After a bit of work, I've made a wrapper which will wrap a class and
allow you to attach listeners for when the methods are called. But I'm
not sure how to list the non-virtual overloads of a member; there
doesn't seem to be anything in __traits to do that.
Code attached. I've attached a new version of my_metastrings.d which has
a workaround to avoid listing 'this' as a class member.
-- Reiner
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: wrapper.d
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20070818/5e6f060a/attachment.ksh>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: my_metastrings.d
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20070818/5e6f060a/attachment-0001.ksh>
More information about the Digitalmars-d
mailing list