From: mhm26@... (matt) Date: 2004-06-17T05:38:27+09:00 Subject: Delayed Instantiation - delayed.rb Here's some code I wrote to delay object instantiation until an object's methods are needed. If there's anything fooey about it, or if there's a better version out there, please let me know :-) --begin-- ######################################################################### ######################################################################### #### delayed.rb: Thunks for Object Insantiation #### #### Author: Matthew Maycock #### #### Email: _mr_bill_98@yahoo.com #### #### Date: June 16th, 2004 AD! #### #### #### #### Purpose: #### #### Delay instantiation of objects until needed. #### #### Overhead given by an extra indirection of dispatch #### #### Use at your own risk! #### #### #### #### License: #### #### The least restrictive license applicable to this software #### #### given that it was written in ruby and uses the ruby library. #### #### I don't really know that much about such things, so if there #### #### isn't anything in the way, consider this released under the #### #### public domain, free for all! #### ######################################################################### ######################################################################### # Delay creation of an object until some method tries to use it. class DelayedInstance < Object def initialize(klass, *args) @object = Object.new ivars = Object.instance_method(:instance_variables) ieval = Object.instance_method(:instance_eval) iclss = Object.instance_method(:class) inspt = Object.instance_method(:inspect) switched = @delayed_switched = false switch = @delayed_switch = Proc.new { raise "Already switched!" if switched switched = @delayed_switched = true @object = klass.send(:new, *args) } delayed_self = self @object.instance_eval { @delayed_parent = delayed_self @delayed_switch = switch @delayed_added = false @delayed_eval = ieval } [:==, :===, :=~, :__id__, :__send__, :class, :clone, :display, :dup, :eql?, :equal?, :extend, :freeze, :frozen?, :hash, :id, :inspect, :instance_eval, :instance_of, :instance_variable_get, :instance_variable_set, :instance_variables, :is_a?, :kind_of?, :method, :methods, :new, :nil?, :object_id, :private_methods, :protected_methods, :public_methods, :remove_instance_variable, :respond_to?, :send, :singleton_method_added, :singleton_method_removed, :singleton_method_undefined, :singleton_methods, :taint, :tainted?, :to_a, :to_s, :type, :untaint].each {|sym| eval <<-END_EVAL def @object.#{sym.to_s}(*args, &block) return super(*args, &block) unless @delayed_added parent = @delayed_parent @delayed_switch[] obj = @delayed_eval.bind(parent).call { @object } obj.send(#{sym.inspect}, *args, &block) end END_EVAL } Object.instance_method(:instance_eval).bind(@object).call {@delayed_added = true} end def method_missing(sym, *args, &block) @delayed_switch[] unless @delayed_switched @object.send(sym, *args, &block) end end [:==, :===, :=~, :__id__, :__send__, :class, :clone, :display, :dup, :eql?, :equal?, :extend, :freeze, :frozen?, :hash, :id, :inspect, :instance_eval, :instance_of, :instance_variable_get, :instance_variable_set, :instance_variables, :is_a?, :kind_of?, :method, :methods, :new, :nil?, :object_id, :private_methods, :protected_methods, :public_methods, :remove_instance_variable, :respond_to?, :send, :singleton_method_added, :singleton_method_removed, :singleton_method_undefined, :singleton_methods, :taint, :tainted?, :to_a, :to_s, :type, :untaint].each {|sym| DelayedInstance.module_eval <<-END_EVAL def #{sym.to_s}(*args, &block) @object.send(#{sym.inspect}, *args, &block) end END_EVAL } if __FILE__ == $0 then class Test def initialize(index) $stdout.puts "Something that takes a thousand hours..." @index = index end def display $stdout.puts @index end end data = (1..10).map {|i| DelayedInstance.new(Test, i)} data.each {|d| d.display} $stdout.puts foo = DelayedInstance.new(Test, 1000) foo.instance_eval { $stdout.puts "Instance Eval!" @santa = 100 } $stdout.puts foo.instance_variables.inspect $stdout.puts foo.instance_eval {@santa} end =begin ### ruby -v: ruby 1.8.1 (2003-12-25) [i386-mswin32] # OUTPUT Something that takes a thousand hours... 1 Something that takes a thousand hours... 2 Something that takes a thousand hours... 3 Something that takes a thousand hours... 4 Something that takes a thousand hours... 5 Something that takes a thousand hours... 6 Something that takes a thousand hours... 7 Something that takes a thousand hours... 8 Something that takes a thousand hours... 9 Something that takes a thousand hours... 10 Something that takes a thousand hours... Instance Eval! ["@index", "@santa"] 100 =end