I have a class Operator
that executes a block of code of some instances of other objects:
class Operator
def operation(&block)
#execution of a block in some object
end
end
In the other hand, I have the class Criature
class Criature
operational
def level_up
@level+=1
end
end
And I need to monkeypatch the class Object
with open class.
So, I need to define the method operational
in Object
, because, every time that an instance of Operator
executes operation
, with (for example) the block: { c.level_up() }
will be executed for every instance with operational
in it's class body.
How can I do to do this?
executes a block of code of some instances of some objects:
If I well understand, with the method
operational
that you want to execute in the body of some classes like Criature
, you want to flag their instances, saying "Hey, give me a call when operation
is performed."
From The Pickaxe :
ObjectSpace.each_object( ‹ class_or_mod› )
Calls the block once for each living, nonimmediate object in this Ruby process. If class_or_mod is specified, calls the block for only those classes or modules that match (or are a subclass of) class_or_mod.
With ObjectSpace
it's possible to iterate over the objects of a certain class. This gives me the idea that the signature, this flag that you want to give to certain instances, can be accomplished with a superclass.
ObjectSpace.each_object(Operational)
will collect all instances of classes having this "signature".
File tc.rb
:
class Operational
end
class Criature < Operational
def initialize(p_name)
@name = p_name
@level = 0
end
def level_up
@level+=1
puts "level is now #{@level}"
end
end
class XYZ < Operational
def initialize(p_name)
@name = p_name
end
end
File to.rb
:
require_relative 'tc'
class Operator
def operation(&block)
#execution of a block in some object
Special.currently_operational.each do | obj |
puts "operation on #{obj.inspect}"
block.call(obj) if obj.respond_to? 'level_up'
end
end
end
class Special
def self.currently_operational
operationals = []
ObjectSpace.each_object(Operational) do | object |
operationals << object
end
puts "#{operationals.size} objects are flagged as operational"
operationals
end
end
Criature.new('c1')
Criature.new('c2')
Criature.new('c3')
block = Proc.new{ | x | x.level_up }
puts 'first round'
Operator.new.operation(&block)
# later ...
XYZ.new('x1')
XYZ.new('x2')
puts 'second round'
Operator.new.operation(&block)
Execution :
$ ruby -w to.rb
first round
3 objects are flagged as operational
operation on #<Criature:0x007fc45683d2f0 @name="c3", @level=0>
level is now 1
operation on #<Criature:0x007fc45683d368 @name="c2", @level=0>
level is now 1
operation on #<Criature:0x007fc45683d3b8 @name="c1", @level=0>
level is now 1
second round
5 objects are flagged as operational
operation on #<XYZ:0x007fc45683cad0 @name="x2">
operation on #<XYZ:0x007fc45683cb48 @name="x1">
operation on #<Criature:0x007fc45683d2f0 @name="c3", @level=1>
level is now 2
operation on #<Criature:0x007fc45683d368 @name="c2", @level=1>
level is now 2
operation on #<Criature:0x007fc45683d3b8 @name="c1", @level=1>
level is now 2