Inheriting from base classes

But a further question is: how fundamental is the inheritance hierarchy
to designing programs in Ruby, given the non-kind_of? underpinnings of
Ruby objects (i.e., their dynanism and “in-the-moment” behavior)?

···

----- Original Message -----
From: dblack@candle.superlink.net


I’m not sure I understand what you mean. kind_of?' determines what methods an object has, even if those methods are dynamically added, or singleton methods, or whatever. Withoutkind_of?’ (meaning the inheritance heirarchy
it represents), Ruby objects would become C structures!

In that quote, matz seemed to be against over-using inheritance. And I
think that’s similar to my original point: don’t subclass from a class
(base class or not) unless you want to use the subclass in place of the
class. Don’t inherit from Array unless you are making a new kind_of? Array;
a class where you will want to use every method Array has, and (perhaps)
then some.

Removing methods from a subclass is generally a sign that it should not be a
subclass, IMHO. (That’s one of the reasons why I think Method should be a
subclass of UnboundMethod, and not the other way around.)

Chris

I don’t see the benefit of this approach over subclassing.

···

On Tue, 11 Feb 2003 23:56:58 +0900, Paul Brannan pbrannan@atdesk.com wrote:

Why not define your own << method? E.g.:

class ImageList
def <<(other)
images << other
end
end

The normal test for subclassing is to see if the question “Is a Y is a
kind of X?” is true for the proposed subclass, when you talk about the
concepts that the subclass represents.

I have a Ruby-specific question about this, which I ask with a bit of
trepidation since I know that OO principles at this level of
abstraction are generally not language-specific…

In Ruby, it seems to me that the module mechanism does a lot to reduce
the importance of the class hierarchy tree. Or, to relate it to your
point, modules add adjectives to the mix. So “Is a Y a kind of X?”
might come out as, “Is a Y a Z-able X?” And the answer to this kind
of question might (?) more often be “Yes.”

Agreed. In Smalltalk, some developers do talk about inheritance purely
for code sharing purposes as distinct from real subclassing. Since Ruby
shares much of Smalltalk’s dynamic nature, the same situation arises.
The only challenge occurs when you find that there are some methods you
do not want to expose in the code sharing subclass.

Is a ClassRoster a kind of Array? Probably false. From the name I’d
guess that ClassRoster represents the group of people attending the
class, and alternate implementations not based on Array are probably
just as useful.

But then there’s the question: if a ClassRoster is essentially an
ordered list of Student objects, and that list is going to be added
to, sorted, subtracted from, mapped over, etc. etc… what is the
disadvantage to having it subclass Array (rather than sort of shadow
Array via instance variables and rewriting of methods that Array
already has)? I’m willing to believe there are disadvantages, but I’m
not succeeding in picturing an actual scenario where it would play out
badly.

Someone else already pointed out the obvious one of the Array getting
the wrong objects put into it, but Test Driven Development is a good
fix for that.

A pragmatic approach (with apologies to Dave and Andy) is to say that
in Ruby it doesn’t matter, because if and/or when it becomes a problem,
changing the implementation of the ClassRoster will not have massive
consequences. After all it is not like we have to recompile
everything:-)

Are AssignmentValues a kind of Hash? Probably false. I cannot guess
from the name what it might represent.

Basically:

Midterm exam => 30%
Term Paper => 30%
Final Exam => 40%

kind of thing. A better name might be CourseRequirements.

Now that I understand the context, AssignmentValues looks reasonable
(“intuitive in hindsight” is how I refer to this). CourseRequirements
invokes the idea of courses that must be taken before this one.

Pete

···

On Tuesday, February 11, 2003, at 07:26 AM, dblack@candle.superlink.net wrote:

On Tue, 11 Feb 2003, Pete McBreen wrote:


Pete McBreen, McBreen.Consulting , Cochrane, AB

Author, “Software Craftsmanship The New Imperative”
Winner of 2002 SD Productivity Award

Author: “Questioning Extreme Programming”
Addison-Wesley (c) 2003

Sorry for being ignorant, but I’m confused. What do you mean by
‘concrete’ vs. ‘base’ classes? When David started this thread he
said…

I think he’s joking. By inheriting from a class, it becomes (by
definition), a base class. “superclass” might be a better term to
use if you consider a “base” class to be the top of a given
inheritance hierarchy.

Then again, maybe I misread the whole thing.

···

=====

Yahoo IM: michael_s_campbell


Do you Yahoo!?
Yahoo! Shopping - Send Flowers for Valentine’s Day

A base class is just a class that you inherit from, e.g.:

class Base
end

class Derived < Base
end

(that is, I think the act of inheriting from a class makes it a base
class).

A concrete base class is a class that you actually intend to
instantiate. In the above example, Base is a concrete base class,
because I can write:

b = Base.new

I might not want to be able to instatiate Base, though, so I might
write:

class Base
private_class_method :new
end

class Derived < Base
public_class_method :new
end

though in many cases this isn’t much different from:

module Base
end

class Derived
include Base
end

C++ also has the notion of a “pure abstract base class” (which is like
an interface in Java). There’s often a distinction made between an
abstract base class and a concrete base class, in C++. Ruby doesn’t
have abstract base classes (at least, not in the sense that C++ has
them), so almost all base classes in Ruby are concrete base classes
(hence dblack’s use of the term “base class”).

Paul

···

On Fri, Feb 14, 2003 at 03:49:51AM +0900, James Davis wrote:

Sorry for being ignorant, but I’m confused. What do you mean by
‘concrete’ vs. ‘base’ classes?

Let me elaborate on this. The behavior of Array does not change, but
if a method in Array depends on one of its method having a particular
behavior, and you change that method in the derived class to have
similar but different behavior, you are likely to break something
(perhaps silently – your unit tests might pass, even though you have a
bug that won’t show up for quite some time).

Paul

···

On Tue, Feb 11, 2003 at 11:50:19PM +0900, Paul Brannan wrote:

Providing checks like this is ugly and unproductive, particularly
since it would change the behavior of the base class.

Michael Campbell wrote:

But a further question is: how fundamental is the inheritance
hierarchy
to designing programs in Ruby, given the non-kind_of? underpinnings
of
Ruby objects (i.e., their dynanism and “in-the-moment” behavior)?

Are you saying here that because it’s easy to not do strict kind-of?
modelling in ruby, that you shouldn’t? Or that existing classes in
ruby don’t do it, so end users shouldn’t have to? Or something else?

Your previous post seemed to indicate you break the kind-of? “rule of
thumb” where it becomes convenient to save typing, which I think is
not the way it should be done. not that I’ve never done the same
thing, but we’re at a more conceptual level with this discussion.
(Or are we? maybe that’s a disconnect.)

I wouldn’t say this is an issue of saving typing (as in pushing keys on
a keyboard). My guess is that David feels that this is the “Ruby spirit”.

I’m a static->dynamic language convert (not that I’m going to preach
about either), and while I understand all of the is-a/has-a stuff and
have practiced it for years, I find that in Ruby I stop worrying about
type so much. I give myself a lot more flexibility to be expressive and
succinct. Maybe I’ll add a method to an existing class. Maybe to an
instance. In languages like Java, I tend to never use the equivalent
of Ruby’s Array in public interfaces, because I’m so driven by the Java
strict typing Way.

So, I see where David’s coming from here. There are rules of thumb on
OO design, but the Ruby environment places higher value on
“responds-to?” than “is-a?” …at least in my interpretation of it.

That having been said, these days I find myself (in Ruby, at least)
almost never inheriting from anything. Again, I’m not dogmatically
saying that you shouldn’t use inheritance. I just tend to do what a)
feels right, b) gets the job done, and c) others can read (if that’s
even necessary).

Chad

Hi –

That’s what you should be aiming for in OO code: users don’t have to
do any low-level stuff on your objects. You implement just the
methods they need. They shouldn’t have to know that Array is used to
implement it.

They don’t; If they’re just require’ing a library, and using the
published/documented interface, that’s all they need to know.

Of course, you need a way of building up a roster. That might be by
parsing a text file, or you may need to resort to:

class ClassRoster
def <<(o)
@roster =
end
end

Rather than say “gosh, what a pain doing such a boring method”, look
for ways to eliminate the need for it.

class ClassRoster < Array # :slight_smile:

Or, if a few such methods are
indeed perfectly justifiable, then use one of Ruby’s forwarding
mechanisms, or try to do more than just delegate (error checking, for
instance).

At the end of the day, the fewer methods per class, the better.
Superfluous methods cloud the intention of the class. (String et al
are excluded from this rule for obvious reasons.)

This comes back to the original question – why? Especially in a
language where runtime objects may or may not correspond to the
capabilities of their (historical) class.

David

···

On Wed, 12 Feb 2003, Gavin Sinclair wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hi –

From: dblack@candle.superlink.net

But a further question is: how fundamental is the inheritance hierarchy
to designing programs in Ruby, given the non-kind_of? underpinnings of
Ruby objects (i.e., their dynanism and “in-the-moment” behavior)?

I’m not sure I understand what you mean. kind_of?' determines what methods an object has, even if those methods are dynamically added, or singleton methods, or whatever. Without kind_of?’ (meaning the inheritance heirarchy
it represents), Ruby objects would become C structures!

I’m not sure I understand that last point, but in any case,
obj.kind_of?(Mod) determines only whether Mod occurs among obj’s
ancestral classes and/or modules. It doesn’t tell you anything about
what the object actually does (i.e., what messages it responds to, and
how).

irb(main):002:0> a = “abc”
“abc”
irb(main):003:0> def a.talk; puts “I’m a talking String!”; end
nil
irb(main):004:0> a.kind_of?(String)
true
irb(main):005:0> b = “def”
“def”
irb(main):006:0> b.kind_of?(String)
true
irb(main):007:0> a.talk
I’m a talking String!
nil
irb(main):008:0> b.talk
NameError: undefined method `talk’ for “def”:String
from (irb):8

It’s possible to write Ruby programs that sort of shadow what you’d
have to do in Ruby if objects didn’t have this dynamism. But they do
:slight_smile:

In that quote, matz seemed to be against over-using inheritance. And I
think that’s similar to my original point: don’t subclass from a class
(base class or not) unless you want to use the subclass in place of the
class. Don’t inherit from Array unless you are making a new kind_of? Array;
a class where you will want to use every method Array has, and (perhaps)
then some.

I interpret Matz’s words very differently. I think what he was saying
is that inheritance, in Ruby, can be viewed as not so much a
hierarchical thing but a kind of borrowing of functionality. In any
case, it’s the object, at runtime, that either can or cannot do
things. It’s true that someone can send an irrelevant message to a
Roster object. But it’s also true that, if someone wants to step
outside the documented interface and mess around with Roster objects,
that person can do:

r = Roster.new
def r.rogue_method … end

David

···

On Wed, 12 Feb 2003, Chris Pine wrote:

----- Original Message -----


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

In the last substantial project I did, using Ruby, I used inheritance,
and realised after a while that it was not even technically necessary.
I could have implemented it without inheritance, taking advantage of
the “responds_to?” over “is_a?” value system.

But sometimes it just makes sense.

The beauty of Ruby is that we don’t have to rely on inheritance in
order to achieve certain things (i.e. we can add methods to existing
classes, we can send messages to any object). But inheritance still
has value as a means of structuring the system.

I actually try to avoid using inheritance until I am certain that it
is justified, in terms of representing structure, and not just (re)using
an implementation. This works well for me as a design/refactoring
compass.

Gavin

···

On Wednesday, February 12, 2003, 3:48:09 AM, Chad wrote:

So, I see where David’s coming from here. There are rules of thumb on
OO design, but the Ruby environment places higher value on
“responds-to?” than “is-a?” …at least in my interpretation of it.

That having been said, these days I find myself (in Ruby, at least)
almost never inheriting from anything. Again, I’m not dogmatically
saying that you shouldn’t use inheritance. I just tend to do what a)
feels right, b) gets the job done, and c) others can read (if that’s
even necessary).

Whoops, didn’t mean to sound like I was mocking your phrase :slight_smile:

David

···

On Wed, 12 Feb 2003 dblack@candle.superlink.net wrote:

I’m not sure I understand what you mean. `kind_of?’ determines what
I’m not sure I understand that last point, but in any case,


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

The fact that Ruby allows such runtime shenanigans doesn’t mean that
they are commonly used.

In most cases, for better or worse, a Ruby object will have exactly
the same methods it was born with.

Runtime tricks are more likely to be used behind the scenes, where the
author of the class knows what is going on. Weird singleton objects
are unlikely to be foisted upon the public, because:

  • such techniques are rarely needed
  • the user can’t look up the documentation for a method that isn’t
    ‘supposed’ (not a moral judgement) to exist

The point I’m trying to make is that the ultra-dynamic features of
Ruby are generally used in libraries, frameworks, etc., behind the
scenes. When John Q Programmer sits down to nut out an application,
he is 99% likely to take a similar approach in Ruby as he would in
Java, except that he notes he is free to do many things should the
need arise. That is: identify some classes, perhaps a hierachy,
imagine the relationships between them, and bang out some
(conservative) code. Test and repeat until it works.

That’s not to suggest that the advanced features of Ruby are a mere
curiosity. Far from it. But if you look at the average case, and
start this debate again, then you might agree with the following
conclusion:

At the end of the day, the fewer methods per class, the better.
Superfluous methods cloud the intention of the class, and make
documentation (the other half of programming) difficult. The lower
quality of documentation multiplies the obfuscation of your total
system with each class, up to and beyond the point where your
daylight hours are plagued by endless questions from the users.

Really, all these “OO rules of thumb” have scalability in mind. As
systems grow large, it becomes more beneficial to keep each component
small, localised, and clear.

Gavin

···

On Wednesday, February 12, 2003, 4:05:43 AM, dblack wrote:

At the end of the day, the fewer methods per class, the better.
Superfluous methods cloud the intention of the class. (String et al
are excluded from this rule for obvious reasons.)

This comes back to the original question – why? Especially in a
language where runtime objects may or may not correspond to the
capabilities of their (historical) class.

Whoops, didn’t mean to sound like I was mocking your phrase :slight_smile:

···

----- Original Message -----

I’m not sure I understand what you mean. `kind_of?’ determines what
I’m not sure I understand that last point, but in any case,


:slight_smile:

Well, I think we might be talking about different things, so our mutual
confusion is understandable.

What I meant by kind_of?' determining what methods an object has is that every method obj’ responds to comes from some class `aClass’ such that:

obj.kind_of? aClass # → true

Even if it’s just a singleton class:

irb(main):001:0> x = Object.new
#Object:0x400d85a4
irb(main):002:0> sc = class << x; self; end
#<Class:#Object:0x400d85a4>
irb(main):003:0> x.kind_of? Object
true
irb(main):004:0> x.kind_of? sc
true

It’s the relationship conveyed by the kind_of?' method that I was referring to. An object is a kind_of?’ many different classes and modules, but it’s
behavior is completely determined by which ones.

I interpret Matz’s words very differently. I think what he was saying
is that inheritance, in Ruby, can be viewed as not so much a
hierarchical thing but a kind of borrowing of functionality.

Oh. Interesting. I thought he was saying that one should often use
‘borrowing of functionality’ (like mixins, singleton classes, etc) instead
of forcing everything into an inheritance heirarchy. It’s also quite
possible that we are both taking him out of context… but that’s what I
think, anyway, even if it’s not what he thinks. :slight_smile:

Chris

Hi –

At the end of the day, the fewer methods per class, the better.
Superfluous methods cloud the intention of the class. (String et al
are excluded from this rule for obvious reasons.)

This comes back to the original question – why? Especially in a
language where runtime objects may or may not correspond to the
capabilities of their (historical) class.

The fact that Ruby allows such runtime shenanigans doesn’t mean that
they are commonly used.

In most cases, for better or worse, a Ruby object will have exactly
the same methods it was born with.

But not always. Class methods are a good example of a very common
form of this kind of change (i.e., they’re singleton methods which
cause Class objects no longer to behave like “pure” instances of
Class).

Runtime tricks are more likely to be used behind the scenes, where the
author of the class knows what is going on. Weird singleton objects
are unlikely to be foisted upon the public, because:

  • such techniques are rarely needed
  • the user can’t look up the documentation for a method that isn’t
    ‘supposed’ (not a moral judgement) to exist

I didn’t realize we were specifically talking about
non-behind-the-scenes usage :slight_smile: In any case, if a method is listed in
an alphabetical list of methods, why would there be any mystery? (I
think we’ve sort of recentered the discussion, not necessarily in a
way that pertains directly to the question of inheriting from base
classes, though I could be wrong.)

The point I’m trying to make is that the ultra-dynamic features of
Ruby are generally used in libraries, frameworks, etc., behind the
scenes. When John Q Programmer sits down to nut out an application,
he is 99% likely to take a similar approach in Ruby as he would in
Java, except that he notes he is free to do many things should the
need arise. That is: identify some classes, perhaps a hierachy,
imagine the relationships between them, and bang out some
(conservative) code. Test and repeat until it works.

But we are behind the scenes here. At least, that’s the interesting
part to me :slight_smile: You’re probably right statistically – I’m just
intrigued by other possibilities, and curious about their viability.

David

···

On Wed, 12 Feb 2003, Gavin Sinclair wrote:

On Wednesday, February 12, 2003, 4:05:43 AM, dblack wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

I don’t know. I am nut’in out a production Ruby application, and I
just did this yesterday (simplified and names changed to protect
innocent):

class Foo
def override_me
end
end

myFoo = Foo.new
def myFoo.override_me
#do something cool
end

Now, i could have created a subclass and instantiated it (which is what
I did do, but not explicitly.)

class MyFoo
def override_me
#do something cool
end
end

myFoo = MyFoo.new

This would be a very Java thing to do…but adding the method to the
object instance just felt (and worked) right. Java has no such
capability. Having written literally hundreds of thousands of lines of
production Java code (and a fair bit o’ Ruby production code) I
approach the two very differently and the way I use classes, modules
and objects is the main difference.

-rich

···

On Tuesday, February 11, 2003, at 04:15 PM, dblack@candle.superlink.net wrote:

The point I’m trying to make is that the ultra-dynamic features of
Ruby are generally used in libraries, frameworks, etc., behind the
scenes. When John Q Programmer sits down to nut out an application,
he is 99% likely to take a similar approach in Ruby as he would in
Java, except that he notes he is free to do many things should the
need arise. That is: identify some classes, perhaps a hierachy,
imagine the relationships between them, and bang out some
(conservative) code. Test and repeat until it works.

But we are behind the scenes here. At least, that’s the interesting
part to me :slight_smile: You’re probably right statistically – I’m just
intrigued by other possibilities, and curious about their viability.

In any case, if a method is listed in an alphabetical list of
methods, why would there be any mystery?

There’s a difference between a theoretical mystery and a practical
mystery. An alphabetical list of methods is one thing, but my reason
for minimising methods is so you can browse the methods of a class
to get an idea of the concept that class espouses.

(I think we’ve sort of recentered the discussion, not necessarily in
a way that pertains directly to the question of inheriting from base
classes, though I could be wrong.)

Whoops, did I do that? :slight_smile:

I’ve stated enough times that inheriting from generic classes without
preserving that generality is bad (IMO), e.g.

class OrderedHash < Hash # good

class AssignmentResults < Hash # bad

And one reason is that you are not putting enough effort into what
methods are available to the users of your class.

So my previous post about the badness of too many methods is
consistent with my point of view on this whole thread.

Gavin

···

On Wednesday, February 12, 2003, 8:15:29 AM, dblack wrote:

Gavin Sinclair wrote:

I’ve stated enough times that inheriting from generic classes without
preserving that generality is bad (IMO), e.g.

class OrderedHash < Hash # good

class AssignmentResults < Hash # bad

And one reason is that you are not putting enough effort into what
methods are available to the users of your class.

So my previous post about the badness of too many methods is
consistent with my point of view on this whole thread.

No such thing as too many methods, just a thing as too many accessible
methods. :slight_smile:

I can’t think it is too difficult to make every method protected when
subclassing and then opening only up those methods that are actually
needed by the outside world.

class Module
def major_inheritance_lockdown
puts “Lock 'er down tight!”
superclass.instance_methods.each{|meth|
protected meth
}
end
end

class AssignmentResults < Hash
major_inheritance_lockdown
public :each, : #etc
end

a = AssignmentResults.new
a[5]=2 #=>toomanymethods.rb:17: protected method `=’ called for
{}:AssignmentResults (NameError)

I’d plug all the holes and loose ends, but I’ve got a pizza is in the
oven.

[insert DuckTyping argument that goes pro this kind of madness here]

In practice, I use SimpleDelegator a lot in this kind of situations, but
I’m somewhat worried about performance with it.

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 5. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)