M
Marnen Laibow-Koser
David said:Hi --
I'm not saying (and I don't think James would say) that this is a
"winner-take-all" situation where we all have to choose one technique
and do only that. But I think extending core objects is a very good
way to add functionality to them.
It sounds like by type-checking you mean class-checking (or
ancestry-checking). It's kind of a circular argument, in the sense
that if you decide that it's important to know an object's class
because you're relying on that to tell you exactly what the object
does, then it's bad if the object does other stuff (i.e., if its type
diverges from its class).
Yes, I suppose it's somewhat circular. If the truth be told, I don't do
a heck of a lot of class checking in Ruby, and I had forgotten that
is_a? checks included modules, which goes a long way toward overcoming
my pragmatic objection.
It's certainly possible to look at things that way, but it seems to me
that it means you're fighting Ruby. The entire thrust of Ruby's object
model is to put the focus on the objects rather than their classes.
(Yes, I know that classes are objects Them too -- which is why
class methods are manifested as singleton methods on class objects,
rather than some completely separate language-level construct.)
Interesting point. Perhaps I misunderstood the language.
Here's one of my favorite historical observations about Ruby, where
ruby10 is the Ruby 1.0 interpreter:
[dblack@ruby-versions ~]$ ruby10 -e 'puts "hi"'-e:1: NameError:
undefined method `puts' for main(Object)
[dblack@ruby-versions ~]$ ruby10 -e 'a = "hi"; class << a; def talk;
print self + "!\n"; end; end; a.talk'
hi!
In other words, Ruby 1.0 had no puts statement... but it *did* have
singleton classes. That's a great corrective to the perception I think
some people have that singleton behaviors are some kind of
meta-wizard-add-on complication to the language.
I don't think I had ever thought that.
They're not; the
language was designed from the beginning to make it possible to
engineer objects on an individual basis.
I figured that.
I've heard people say that, while that's true, it's undisciplined to
actually use any of these techniques. I disagree radically. Of course,
I don't spend all that much of my time as a Ruby programmer writing
singleton methods -- but I do regard the individual object as the
center of gravity, and I regard classes largely as a convenience-macro
for creating objects bundled with certain behaviors at their birth
that may or may not represent what they do during their lifetimes.
In other words, you're advocating writing Ruby rather like JavaScript.
That makes some sense -- although, as a devil's advocate, I could ask
why, in that case, Matz didn't design the language with a prototype
model.
This is also why, in my book and in my training, I present singleton
methods *first*, and classes second. (And I completely understand why
Matt Neuberg introduces modules before classes[1] -- which I usually
don't but it's an extremely intriguing idea.)
Do you worry that this will cause people to excessively avoid classes in
favor of singleton mixins? Or is that the idea?
Classes exist in Ruby, and no one is awarding points based on how many
singleton methods one writes. But for me, anyway, the class part of
the model floats on top of the real business, which is the objects.
That's an interesting point of view. I was about to ask why you believe
that, but then I realized that the fact that Ruby allows so much
singleton manipulation kind of supports that point.
So
I don't like to commit myself to having things break just because
objects aren't aligned perfectly type-to-class.
Nor do I. I certainly don't write code that will do that in the first
place...
(There's more to say but that's long enough for now
David
Best,