Apart from the ways that were already mentioned you can also do this:
obj = Class.new { def bar() puts "foo" }.new
class Foo
define_method(:bar, &obj.method(:bar))
end
But note that this is the same as doing this:
class Foo
define_method(:bar) { obj.method(:bar).call }
end
I've posted in this thread already that EvilRuby is less restrictive with Method#force_bind, but I don't think that this is needed in your case. (It could however be useful to implement AOP-like stuff.)
THANK you for this intelligent reply, this is what I was looking for.
Perhaps another poster was correct, 'you can do everything in Ruby'
best regards,
George.
"G" == George Moschovitis <george.moschovitis@gmail.com> writes:
> however, I would like to use it carefully. My question was: is this
> possible?
Well, you can use #instance_method and #bind but ruby will make the test
uln% ruby -e 'Array.instance_method(:).bind(Hash.new)'
-e:1:in `bind': bind argument must be an instance of Array (TypeError)
Note that EvilRuby has a less strict version of UnboundMethod#bind (#force_bind) which will work in this case:
class Foo
def x() end
end
class Bar
end
Foo.instance_method(:x).bind(Bar.new) # raises TypeError
Foo.instance_method(:x).force_bind(Bar.new) # works
Hash.instance_method(:).force_bind(Array.new) # still doesn't work
Well, I know about modules, this is not what I want.
I want to inject only ONE method from a class containing multiple
methods into another.
-g.
Object methods do not work in vacuum, they usually use instance variables to reffer to the object's state, possibly changing it (remember encapsulation ;-)?). How would you expect your inject_method() deal with it?
Object methods do not work in vacuum, they usually use instance
variables to reffer to the object's state, possibly changing it
(remember encapsulation ;-)?). How would you expect your
inject_method() deal with it?
I thought Ruby promotes 'duck typing'.
I would like to inject specific methods between specific classes. The
destination class has all the instance variables needed to succesfully
execute the method.
Object methods do not work in vacuum, they usually use instance
variables to reffer to the object's state, possibly changing it
(remember encapsulation ;-)?). How would you expect your
inject_method() deal with it?
I thought Ruby promotes 'duck typing'.
I would like to inject specific methods between specific classes. The
destination class has all the instance variables needed to succesfully
execute the method.
I do not think what you want has anything to do with 'duck typing'. 'duck typing' only means that you can send a message to any object and if the object has a corresponding method it gets executed regardless of object type. It does not urge you to abandon the "normal" way of method definition for a class.
In general, I am very cautious to dynamically adding methods down the road, as it greatly increases the risk of your system becoming incomprehensible.
As somebody has indicated, Ruby has other ways to "inject" methods in some controlled manner, like mixins or inheritance. I would consider them first before resorting to any sort of "tricks", even if they were possible (everything is possible in Ruby, you know ;-), one way or another).
"George Moschovitis" <george.moschovitis@gmail.com> schrieb im Newsbeitrag
news:1106667522.708436.185960@z14g2000cwz.googlegroups.com...
> Object methods do not work in vacuum, they usually use instance
> variables to reffer to the object's state, possibly changing it
> (remember encapsulation ;-)?). How would you expect your
> inject_method() deal with it?
I thought Ruby promotes 'duck typing'.
I would like to inject specific methods between specific classes. The
destination class has all the instance variables needed to succesfully
execute the method.
And what about other methods that are used by a method? I think it's not
generally possible to move methods around.
But maybe this trick helps:
class Object
def cast(target_class)
copy = case target_class
when Class; target_class.allocate
when Module; dup
else target_class.class.allocate
end
instance_variables.each do |var|
copy.instance_variable_set(var, instance_variable_get(var))
end
copy
end
end
Then you can create a tmp copy of an instance with all instance variables
copied but a different class. So you can do
foo.cast(Bar).bar_method_to_be_called().
That's not duck typing, it's duck cloning, Dr. Frankenstein!
···
On Wed, 26 Jan 2005 00:40:49 +0900, George Moschovitis <george.moschovitis@gmail.com> wrote:
> Object methods do not work in vacuum, they usually use instance
> variables to reffer to the object's state, possibly changing it
> (remember encapsulation ;-)?). How would you expect your
> inject_method() deal with it?
I thought Ruby promotes 'duck typing'.
I would like to inject specific methods between specific classes. The
destination class has all the instance variables needed to succesfully
execute the method.
"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag
news:35nafhF4of2saU1@individual.net...
"George Moschovitis" <george.moschovitis@gmail.com> schrieb im
Newsbeitrag
news:1106667522.708436.185960@z14g2000cwz.googlegroups.com...
> > Object methods do not work in vacuum, they usually use instance
> > variables to reffer to the object's state, possibly changing it
> > (remember encapsulation ;-)?). How would you expect your
> > inject_method() deal with it?
>
> I thought Ruby promotes 'duck typing'.
>
> I would like to inject specific methods between specific classes. The
> destination class has all the instance variables needed to succesfully
> execute the method.
And what about other methods that are used by a method? I think it's
not
generally possible to move methods around.
But maybe this trick helps:
Should've read
class Object
def cast(target_class)
copy = case target_class
when Class; target_class.allocate
when Module; dup.extend(target_class)
else target_class.class.allocate
end
instance_variables.each do |var|
copy.instance_variable_set(var, instance_variable_get(var))
end
copy
end
end
Then you can create a tmp copy of an instance with all instance
variables
···
copied but a different class. So you can do
foo.cast(Bar).bar_method_to_be_called().
I do not think what you want has anything to do with 'duck typing'.
Of course it has. Have a look at the following example:
class C1
attr_accessor :a
def a1
puts @a
end
def a2
puts 'hello'
end
end
class C2
attr_accessor :a
end
So for method C1#a1 the class C2 'quacks like a duck' (ie, it has the
attribute @a)
So in 'duck typing' spirit, it should be possible to do:
c = C2.new
m = C1.instance_method(:a1)
m.bind(c)
c.a1
however Ruby raises a TypeError
Can anyone give me an example, where this #bind method is usefull? I
mean, you can only bind a Method back to an object of the original
method's Class or a Subclass. But such an object allready has this
method, so whats the point?
Am I missing something here?