diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1999-01-20 04:59:39 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1999-01-20 04:59:39 +0000 |
commit | 210367ec889f5910e270d6ea2c7ddb8a8d939e61 (patch) | |
tree | feb35473da45947378fbc02defe39bcd79ef600e /lib/delegate.rb | |
parent | 9c5b1986a36c7a700b4c76817e35aa874ba7907c (diff) | |
download | ruby-210367ec889f5910e270d6ea2c7ddb8a8d939e61.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r372,
which included commits to RCS files with non-trunk default branches.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@373 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/delegate.rb')
-rw-r--r-- | lib/delegate.rb | 100 |
1 files changed, 91 insertions, 9 deletions
diff --git a/lib/delegate.rb b/lib/delegate.rb index e5943cead8..0771f2feeb 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -1,26 +1,51 @@ # Delegation class that delegates even methods defined in super class, # which can not be covered with normal method_missing hack. # -# Delegater is the abstract delegation class. Need to redefine -# `__getobj__' method in the subclass. SimpleDelegater is the +# Delegator is the abstract delegation class. Need to redefine +# `__getobj__' method in the subclass. SimpleDelegator is the # concrete subclass for simple delegation. # # Usage: # foo = Object.new -# foo = SimpleDelegater.new(foo) -# foo.type # => Object +# foo2 = SimpleDelegator.new(foo) +# foo.hash == foo2.hash # => true +# +# Foo = DelegateClass(Array) +# +# class ExtArray<DelegateClass(Array) +# ... +# end -class Delegater +class Delegator def initialize(obj) - preserved = ["id", "equal?", "__getobj__"] + preserved = ::Kernel.instance_methods + preserved -= ["to_s","to_a","inspect","==","=~","==="] for t in self.type.ancestors preserved |= t.instance_methods - break if t == Delegater + preserved |= t.private_instance_methods + preserved |= t.protected_instance_methods + break if t == Delegator end for method in obj.methods next if preserved.include? method - eval "def self.#{method}(*args); __getobj__.send :#{method}, *args; end" + eval <<-EOS + def self.#{method}(*args, &block) + begin + __getobj__.__send__(:#{method}, *args, &block) + rescue Exception + c = -caller(0).size + if /:in `__getobj__'$/ =~ $@[c-1] #` + n = 1 + else + c -= 1 + n = 2 + end + $@[c,n] = nil + raise + end + end + EOS end end @@ -30,7 +55,7 @@ class Delegater end -class SimpleDelegater<Delegater +class SimpleDelegator<Delegator def initialize(obj) super @@ -41,4 +66,61 @@ class SimpleDelegater<Delegater @obj end + def __setobj__(obj) + @obj = obj + end +end + +# backward compatibility ^_^;;; +Delegater = Delegator +SimpleDelegater = SimpleDelegator + +# +def DelegateClass(superclass) + klass = Class.new + methods = superclass.instance_methods + methods -= ::Kernel.instance_methods + methods |= ["to_s","to_a","inspect","==","=~","==="] + klass.module_eval <<-EOS + def initialize(obj) + @obj = obj + end + EOS + for method in methods + klass.module_eval <<-EOS + def #{method}(*args, &block) + begin + @obj.__send__(:#{method}, *args, &block) + rescue + $@[0,2] = nil + raise + end + end + EOS + end + return klass; + end + +if __FILE__ == $0 + class ExtArray<DelegateClass(Array) + def initialize() + super([]) + end + end + + ary = ExtArray.new + p ary.type + ary.push 25 + p ary + + foo = Object.new + def foo.test + 25 + end + def foo.error + raise 'this is OK' + end + foo2 = SimpleDelegator.new(foo) + p foo.test == foo2.test # => true + foo2.error # raise error! end |