But if your complaint with Ruby's OO system is that it cannot easily implement a prototyped system, that's like saying that Perl is more OO than JavaScript because it is easier to implement a prototyped system in Perl than to implement multiple inheritance in JavaScript. This is true, but irrelevant - Perl's support for OO everywhere is not as pervasive as JavaScript's.
Furthermore you're mistaken. I found a trivial implementation here:
While I don't doubt that there are many good class implementations in JavaScript, I doubt that any are as short and cute as this prototype implementation in Ruby. Follow the link for a demonstration of usage. While I have to admire how cleverly it ties objects to classes, it unfortunately doesn't work with ancient versions of Ruby such as the one I have on my computer. (Ruby 1.6.8 complains that you can't create a subclass of Class. That version is from 2002.)Proto = Class.new(Class) # Beware: magic. def Proto.clone Class.new(self) end
There is also prototype in the Ruby gems library. I didn't like some things about it (in particular it looks like it doesn't support noticing that the prototype changed), so I implemented my own reasonably full-featured system using a minimum of strange magic that works even in ancient versions of Ruby:
Now let's demonstrate usage:class PrototypeClass attr_reader :prototype def initialize (prototype) @prototype = prototype end def new (*definitions) new_class = Class.new(self.class) # With a modern Ruby you could use caller to find the # file and line, then pass it in to give better error reporting. for definition in definitions new_class.module_eval definition end return new_class.new(self) end def def (definition) # With a modern Ruby you could use caller to find the # file and line, then pass it in to give better error reporting. self.class.module_eval "def #{definition} end" end def include (*mod) self.class.module_eval "include #{mod,join ', '}" end end Prototype = PrototypeClass.new(nil)
As you can see, you have to pass definitions in as strings (boo, hiss), but you have access to all of the normal features of Ruby objects. You can easily define objects, with prototypes, add accessors, add functions, etc. Furthermore the prototype class remains open - change it and you'll pick up changes in inherited classes. (Unless the inherited classes have overwritten them.)@foo = Prototype.new %q{ attr_accessor :name } @bar = @foo.new @baz = @bar.new @foo.name = "foo" @bar.name = "bar" @baz.name = "baz" def test_greet try_greet = lambda {|obj| if obj.respond_to? :greet obj.greet(obj.name) else puts "Object #{obj.name} (#{obj.id}) cannot greet" end } try_greet[@foo] try_greet[@bar] try_greet[@baz] end test_greet() @bar.def %q{ greet (name) puts "Greeting from #{name} (id #{self.id})" } puts "Defined bar.greet" test_greet() module Mod def greet (name) puts "Hello from #{name} (#{self.id})" end end @foo.include(Mod) puts "Included module" test_greet()
Do you still think that JavaScript is more OO than Ruby?
In reply to Re^5: I dislike object-oriented programming in general
by tilly
in thread I dislike object-oriented programming in general
by vrk
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |