I agree with Samir that it just sounds like duck typing. You don't need to care what 'type' an object really 'is' you only need bother with what an object can 'do'. This is true in both Ruby and Python.
However if you really are checking the types of classes and you really do need to have a Poodle
object optionally also be a FurCoat
at runtime, then the way to do this in Ruby is to mixin a FurCoat
module into the Poodle
object, as follows:
class Poodle; end
module FurCoat; def wear; end; end
my_poodle = Poodle.new
my_poodle.is_a?(Poodle) #=> true
my_poodle.is_a?(FurCoat) #=> false
my_poodle.wear #=> NoMethodError
# now we mix in the FurCoat module
my_poodle.extend(FurCoat)
# my_poodle is now also a FurCoat
my_poodle.is_a?(Poodle) #=> true (still)
my_poodle.is_a?(FurCoat) #=> true
my_poodle.wear #=> the wear method now works
EDIT (due to your updated question):
You still do not need to rewrite Class
to achieve what you want, you just need to monkey-patch the kind_of?
and is_a?
(and potentially instance_of?
) methods on Ruby's Kernel
module. Since Ruby has open classes this is easily done:
class Module
def obj_implements_interface?(obj)
false
end
end
module Kernel
alias_method :orig_is_a?, :is_a?
def is_a?(klass)
orig_is_a?(klass) || klass.obj_implements_interface?(self)
end
end
And then define for each class (or module) what it means for an object to implement its interface:
class Dog
def self.obj_implements_interface?(obj)
obj.respond_to?(:bark) && obj.respond_to?(:num_legs) && obj.num_legs == 4
end
end
module FurCoat
def self.obj_implements_interface?(obj)
obj.respond_to?(:wear)
end
end
Now test it:
my_poodle = Poodle.new
my_poodle.is_a?(FurCoat) #=> false
# now define a wear method on my_poodle
def my_poodle.wear; end
my_poodle.is_a?(FurCoat) #=> true