From: Daniel Schierbeck Date: 2006-07-25T07:50:11+09:00 Subject: Re: I'll have the duck! Daniel DeLorme wrote: > benjohn@fysh.org wrote: >> I also like it because I don't think that there's anything especially >> fundamental about classes. With predicate classes, all you're really >> saying is that "if I've got something that can do x and y, then I know >> that I can equally validly think of it as something that can do z". > > The concept really piqued my interest, and since ruby gives us such nice > metaprogramming abilities, why not do it? > > > module DuckTyping > @@quacks = Hash.new{ |h,k| h[k] = {} } > > def ducktype(*reqs, &block) > o = Object > before = o.methods > o.class_eval(&block) > after = o.methods > > for methodname in (after - before) > @@quacks[methodname.to_sym][reqs] = > o.instance_method(methodname.to_sym) > o.send(:remove_method, methodname.to_sym) > end > end > > def ducktype_method(methodname) > @@quacks[methodname.to_sym].each do |reqs, m| > if reqs.all?{ |r| self.respond_to?(r) } > return m > end > end > return nil > end > > def method_missing(methodname, *args, &block) > if m = ducktype_method(methodname) > m.bind(self).call(*args, &block) > else > super > end > end > end > Object.module_eval{ include DuckTyping } > > > ducktype :quack do > def quack_loudly > quack.upcase > end > end > > > class Duck > def quack > "quack!" > end > end > > class Dog > def bark > "woof!" > end > end > > Duck.new.quack_loudly #=> "QUACK!" > Dog.new.quack_loudly #=> NoMethodError > > > nifty? Isn't this stuff used i Aspect Oriented Programming as well? I only know what I've read in the RCR, so I'm not sure. Cheers, Daniel