first time at stack overflow.
I'm looking into using some of the metaprogramming features provided by Ruby or Python, but first I need to know the extent to which they will allow me to extend the language. The main thing I need to be able to do is to rewrite the concept of Class. This doesn't mean that I want to rewrite a specific class during run time, but rather I want to make my own conceptualization of what a Class is. To be a smidge more specific here, I want to make something that is like what people normally call a Class, but I want to follow an "open world" assumption. In the "closed world" of normal Classes, if I declare Poodle to be a subclass of Dog to be a subclass of Animal, then I know that Poodle is not going to also be a type of FurCoat. However, in an open world Class, then the Poodle object I've defined may or may not be and object of type FurCoat and we won't know for sure until I explain that I can wear the poodle. (Poor poodle.) This all has to do with a study I'm doing concerning OWL ontologies.
Just so you know, I've tried to find information online, but due to the overloading of terms here I haven't found anything helpful.
Super thanks, John
UPDATE: I just thought of a good use case for my open-world concept of Class. Perhaps this will provide a better understanding of what I really wish to do. I want to be able to "describe" a Class rather than define it. For instance, I want to be able to say that a Dog is anything that a) has four legs b) barks. Then I want to be able to create an object of unspecified Class, and describe that this object has four legs. At this point the object is still of unspecified type. Then I want to say that the object barks. At this point, the object will be known to be (possibly among other things) a Dog.
Sounds like duck typing to me. Just declare the methods you want and remember that it's easier to ask forgiveness than permission:
try:
poodle.wear()
except (AttributeError, TypeError):
pass
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With