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 27 Feb 2015, at 03:43, Alexandre Bergel <alexandre.bergel@me.com> 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. ^ selfNote 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
^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.