Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Ruby or Python can the very concept of Class be rewritten?

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.

like image 857
JnBrymn Avatar asked May 23 '10 00:05

JnBrymn


2 Answers

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
like image 92
Samir Talwar Avatar answered Sep 20 '22 14:09

Samir Talwar


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
like image 29
horseyguy Avatar answered Sep 19 '22 14:09

horseyguy