--- 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/