Another way to go is just to do this:

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ProtoObject subclass: #MyProxy
        instanceVariableNames: 'object'
        classVariableNames: ''
        category: ‘'

MyProxy >> initialize
        object := self

MyProxy >> doesNotUnderstand: aMessage
        ^ object perform: aMessage selector withArguments: aMessage arguments

Object >> wrap
        self become: MyProxy new

Object >> isProxy
        ^ false

MyProxy >> isProxy
        ^ true
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

So the idea is that the reference to self in MyProxy becomes the wrapped object 
using the become.

The main problem of this kind of implementation is that self is bounded to the 
proxy, so all the internal calls of self are not going to be intercepted and 
the return self is going to expose the original object.

|obj|
obj := Object new.
obj isProxy. “false"
obj wrap.
obj isProxy. “true”
obj yourself isProxy “false”  <—— This one kind of break the proxy

Cheers,
Alejandro

> On Feb 27, 2015, at 9:35 AM, Camille <[email protected]> wrote:
> 
>> 
>> On 27 Feb 2015, at 03:43, Alexandre Bergel <[email protected]> wrote:
>> 
>> Hi!
>> 
>> I have a near-to-be naive question. Maybe there is something obvious, but I 
>> cannot see it. Consider the following implementation of a proxy:
>> 
>> -=-=-=-=-=-=-=-=-=-=-=-=
>> Object subclass: #MyProxy
>>      instanceVariableNames: 'object'.
>> 
>> MyProxy >> object: anObject
>>      object := anObject
>>      
>> MyProxy >> doesNotUnderstand: aMessage
>>      ^ object perform: aMessage selector withArguments: aMessage arguments
>>      
>> Object >> wrap
>>      self becomeForward: (MyProxy new object: self; yourself)
>> -=-=-=-=-=-=-=-=-=-=-=-=
>> 
>> The problem is with wrap. After the becomeForward:, MyProxy has itself in 
>> the object variable. Even self is apparently subject to the #become.
>> 
>> It means that the following code loop indefinitely
>> 
>> -=-=-=-=-=-=-=-=-=-=-=-=
>> d := Dictionary new.
>> d wrap.
>> d add: #foo -> 10
>> -=-=-=-=-=-=-=-=-=-=-=-=
>> 
>> I know there is Mariano’s library to write proxy. But I still wondering 
>> whether this could be done simply.
>> Any idea how to simply create a proxy?
> 
> Hi Alexandre,
> 
> You have to store the target and the proxy in different temps, do the become 
> and (re)set the link between both after. Or in your case, something like:
> 
> Object >> wrap
>       | proxyThenTarget |
>       proxyThenTarget := MyProxy new.
>       self become: proxyThenTarget.
>       “Now self is the proxy"
>       self object: proxyThenTarget.
>       ^ self
> 
> Note that by subclassing Object many messages won’t be intercepted. With your 
> dictionary example it means that you cannot intercept #at: . Subclassing 
> ProtoObject reduces the number of such messages.
> Also one can bypass these methods by sending #doesNotUndestand: to the proxy. 
> In the end all depends on your requirements: do you care about uniformity 
> (all messages must be intercepted), composition of proxies, security (no 
> target leaks, no interception bypass), what operations do you want to 
> intercept (just message sends or iv accesses in addition), etc...
> For most cases Ghost is the way to go. 
> 
> Camille
> 
>> 
>> Cheers,
>> Alexandre
>> 
>> -- 
>> _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:
>> Alexandre Bergel  http://www.bergel.eu <http://www.bergel.eu/>
>> ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.

Reply via email to