[Note: parts of this message were removed to make it a legal post.]
On May 29, 2008, at 2:14 AM, David Masover wrote:
>>
>> I can say
>> quite categorically, that in OOP, classes are ways to generalize. You
>> generalize based on characteristics and behaviors. A class is not
>> simply a random collection of methods. It would be rather useless if
>> class was unrelated to category.
>
> I'm going to have to respectfully disagree here.
I'm not sure what you're disagreeing with, here. That classes are
categories? If so, I could refer you to any number of the sources I
learned OOP from - except that I've given them all away by now.
If classes are not categories, what are they?
> Unless you are going to have branching based on type -- that is,
> simple method
> overloading (as in C++ and friends) -- I don't see as much point to
> a rigid
> type system.
I've done a lot of C++, and I remember when RTTI (runtime type
information) was introduced. I was pretty strongly against its use,
believing that polymorphism through virtual functions was the way to
"branch" on type. I would have strongly avoided code like v === Numeric.
As I would avoid it today, in Ruby. We're actually talking about
something that I think should be rare, which is branching on type.
We're only doing it to validate parameters. In good Ruby, we would not
do this, relying on the runtime to tell us when we're using the wrong
type. To me, duck typing doesn't mean "ask me if I quack" as much as
"quack, you!". So I think this whole discussion is about an edge case.
> It boils down to: Why should I care whether I'm being passed a
> number or
> something which merely behaves like a number? Why should I care if
> I'm being
> passed a string or an array of characters?
Actually, I agree, in general, and this discussion has clarified the
concept for me.
>
> Now, for the simple case of a Numeric, we're probably over-analyzing
> it.
Yes, I don't think I would have made the same case for a less basic
class.
However, I still think using responds_to? to identify an object's type
is risky. As I said, it relies upon a much larger namespace than class
constants, hence much more chance for accidental positives (e.g.,
#draw meaning different things to different objects).
>> But I'm finding these remarks about "attititude" kind of amusing.
>> It's
>> like Ruby isn't a tool, it's a "mindset." We don't forgo something
>> like Numeric === v because it's _wrong_ (the OP in fact said it was
>> slightly more readable), but because Ruby has duck-typing,
>
> Well, there is some truth to that -- as an example, Ruby completely
> lacks
> anything resembling the C for loop. If that's what you're expecting,
> you have
> to build it out of a while loop:
>
> i=0
> while i < data.length
> do_something_with data[i]
> i += 1
> end
>
> There's nothing wrong with that. But I hope most of us forgo it in
> favor of:
>
> data.each { |datum|
> do_something_with datum
> }
>
> Which ends up being more readable, among other things.
Exactly. It has absolutely nothing to do with Ruby's "mindset," or
"the way we do things in Ruby." We choose the latter because it's
better, not because it's the Ruby way. It's the other way around: it's
the Ruby way because it's better; not that it's better because it's
the Ruby way. The former attitude is pragmatic, the latter is religious.
> But if you do that, I don't understand why you're using Ruby. Again,
> nothing
> wrong with it -- do whatever makes you happy, and maybe you're right
> and I'm
> wrong. But I doubt I'll ever understand it.
There _is_ something wrong with it. It's harder to read and more prone
to error.
> Can you outline a few real-world examples, where it's OK to get a
> descendant
> of Numeric, but not something which merely implements to_i or to_f?
The obvious case is an object that implements to_i in a noncongruent
way. For example, let's say the number passed in is to be used as a
count. An IP address may respond to to_i, but it can't possibly be
correct in this context.
>> True. And often the most straightforward and fundamental way to do
>> that is to call its #class method.
>
> Not really.
>
> Firstly, #class doesn't provide any way to be in multiple
> categories. Ruby
> doesn't support multiple inheritance.
We're not talking about multiple categories - just one. In all my
years of using MI in C++, I've very rarely, if ever, seen a class that
didn't have a "dominant" base class. Most of the time MI is used for
mixing in. You might have a class, for example, that descends both
from Numeric and Observable, but obviously, its main category is
Numeric. In the case under discussion, I don't think multiple
categories are relevant.
At any rate, even if you don't think we should be using #class, you
can sure bet the language disagrees! We wouldn't get very far without
it.
I was emailcommunicado for a day or so, so I'm trying to catch up and
I'm running out of steam, here. ...
///ark