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?