Eric Mahurin wrote:
Eric Mahurin wrote:
Regarding duck-typing... Is there an easy way make a
"duck"?
i.e. an object that responds to enough methods to be an
acceptable argument to a certain methods. For example, if
I
have a method that takes aString and uses the #size and
#[i]
methods, I could pass it something that looked just enough
like
a String to work:
alphabet = Object.duck(:,proc{|i|?a+i},:size,proc{26})
Why aren't you satisfied with
class Alpha
def (i) ?a+i end
def size() 26 end
end
alphabet = Alpha.new
or
alphabet = Object.new
def alphabet.(i) ?a+i end
def alphabet.size() 26 end
You can even squeeze that on one line if you feel the need
for it. I
mean, you don't generate those methods dynamically or get
them from
somewhere else so why not just use the std approach?
For the example I gave above, I think you are correct. The
examples I gave in response to David Black are probably better
ones. With those, a simple "def" won't cut it. You need
define_method. But, using define_method is cumbersome from an
object because you first need to make it have a singleton
class, then use "send" to access it from that class because it
it a private method. Another solution to the problem of
"making a duck" would be to have a
Object#define_singleton_method:
class Object
def define_singleton_method(name,&block)
klass = (class << self;self;end)
klass.send(:define_method,name,&block)
self
end
end
Btw, you can also use class eval:
class Object
def define_singleton_method(name,&block)
klass = (class << self;self;end).class_eval do
define_method(name,&block)
end
self
end
end
and also
o=Object.new
class <<o;self;end.class_eval do
def bax() "bar" end
end
o.bax
Then, for example, you could do this to make a set be useful
for a method that uses == for comparison:
seteq = Object.new.
define_singleton_method(:==,&set.method(:include?))
This does not work. You cannot transfer a method from one class to
another:
09:14:01 [ruby]: cat define.rb
class Foo
def test() bar() end
def bar() "FOO::BAR" end
end
class Bar
def bar() "BAR::BAR" end
end
bar = Bar.new
bar_kl = (class<<bar;self;end)
bar_kl.send(:define_method, :xxx, Foo.new.method(:test))
bar_kl.send(:public, :xxx)
bar.xxx()
09:15:33 [ruby]: ruby define.rb
define.rb:16:in `xxx': bind argument must be an instance of Foo
(TypeError)
from define.rb:16
I'm not sure why this isn't in Object right now. It seems like
the rest of the *singleton_method* methods are there.
Probably because it doesn't work - at least not completely the way you
like to have it. Btw, and if you're borrowing implementations from other
classes then you can directly use an instance of that class...
Kind regards
robert
···
--- Robert Klemme <bob.news@gmx.net> wrote: