mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
9c5b1986a3
commit
210367ec88
140 changed files with 25635 additions and 14037 deletions
100
lib/delegate.rb
100
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue