From: jason@... (Jason Voegele) Date: 2001-09-29T04:30:30+09:00 Subject: [ruby-talk:21814] Pseudo-Become operator for Ruby (was: Transparent Proxies) With some help from this newsgroup, I've come up with a scheme for a "become" like mechanism for Ruby. It is not a true "become" operator because it does not allow any arbitrary object to become any arbitrary thing, but it does allow instances of a proxy class to become any object you desire. The idea is that there is a proxy object that undefines all methods, and then uses the "method_missing" method to trap messages, and then "becomes" the object which it was fronting for. This allows for such things as lazy initialization, and most importantly for my application (a persistent object store) loading objects on demand. Here's an example: class ProxyTest def initialize # create a proxy object so that the array object is only # created when it is first accessed. @lazily_loaded_array = ObjectProxy.new(self, "@lazily_loaded_array") { # This "factory" block simply returns a new array, # but it could conceivably do anything it wants # to retrieve the object, such as load it from # an OO database. Array.new } end def test_proxy # once we call a method on the proxy object, # it should "become" an array puts @lazily_loaded_array.type # -> "Array" @lazily_loaded_array.push(10) puts @lazily_loaded_array.length # -> 1 end end ProxyTest.new.test_proxy Below is the code for the ObjectProxy class. Please let me know if you have any suggestions or comments. Thanks Jason Voegele class ObjectProxy undef_method :== undef_method :=== undef_method :=~ undef_method :class undef_method :clone undef_method :display undef_method :dup undef_method :eql? undef_method :equal? undef_method :extend undef_method :freeze undef_method :frozen? undef_method :hash undef_method :id undef_method :inspect undef_method :instance_eval undef_method :instance_of? undef_method :instance_variables undef_method :is_a? undef_method :kind_of? undef_method :method undef_method :method_missing undef_method :methods undef_method :nil? undef_method :private_methods undef_method :protected_methods undef_method :public_methods undef_method :respond_to? undef_method :send undef_method :singleton_methods undef_method :taint undef_method :tainted? undef_method :to_a undef_method :to_s undef_method :type undef_method :untaint # The proxy object takes a block that retrieves # or creates the object. The container reference is # necessary so that we can break into it and replace # its reference to the proxy with a reference to the # actual object. def initialize(container, variable_name, *args, &factory) @container = container @name = variable_name @factory_args = args @factory = factory end def method_missing(method, *args) become = @factory.call @container.instance_eval("#@name = become") become.send(method, *args) end end