--- Robert Klemme <bob.news / gmx.net> wrote: > Eric Mahurin wrote: > > --- Robert Klemme <bob.news / gmx.net> 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 If you put an & in front of your "Foo.new.method(:test)" (like what I did), or .to_proc it will work fine. __________________________________ Discover Yahoo! Use Yahoo! to plan a weekend, have fun online and more. Check it out! http://discover.yahoo.com/