Do you nest classes inside classes?


#1

Object Orientation is conceptually about a sea of objects interacting
with each other. They are all however in one sea.

Earlier in Computer Science, we had stepwise refinement, which was a
tree-like view of application compartmentalisation. High level functions
would be split into lower level consituents and so on.

I was thinking to model that in Ruby you would like to be able to
contain classes within other classes in a similar tree like format, and
what a shame that Ruby doesn’t let you do that.

But of course it does. However people don’t talk about it. Hal F. in
his book The Ruby Way asks people to let him know if they can think of a
good use for this feature.

Do you ever use this? Can you see a reason why it doesn’t seem to be
favoured?


#2

2009/5/25 Mike S. removed_email_address@domain.invalid

But of course it does. However people don’t talk about it. Hal F. in
his book The Ruby Way asks people to let him know if they can think of a
good use for this feature.

Do you ever use this? Can you see a reason why it doesn’t seem to be
favoured?

I use classes as namespaces quite a lot. Typically, I will nest a class
inside another if the inner class is used directly only by the outer
class
and not by other parts of the system. It’s not a hard-and-fast rule but
I
find this to be a useful organisational feature.


#3

Mike S. removed_email_address@domain.invalid writes:

But of course it does. However people don’t talk about it. Hal F. in
his book The Ruby Way asks people to let him know if they can think of a
good use for this feature.

Do you ever use this? Can you see a reason why it doesn’t seem to be
favoured?

The problem here is the collusion between two notions: that of
namespace and that of class.

There’s no reason, a-priori, why both notion should match. (In some
languages such as Common Lisp, they don’t).

In Ruby, you could use a module as a pure namespace, and avoid putting
classes inside classes: when you have “private” classes you want to
keep in a specific namespace, it would be better IMO to put them in a
module rather in a class.

A good example, would be any abstract data type that needs some
internal structure, eg. a Tree with Node. If the nodes are not part
of the public API of the tree, there’s no reason to make them public,
so it would be good to hide them in some namespace specific to the
tree. But as I said above, I think it would be better to use a module
to package them.


#4

Hi Mike,

Ruby and list noob here. Generally I think using nested classes for real
helper classes that can conceptually only be for use with the parent
class is a useful way of avoiding namespace clutter. I’d be careful of
building large hierarchies, especially deep ones tho. I feel if your
goal is nice decoupling then you want small distinct usable
classes/objects. Also I guess if you’re more of an agile developer, the
hierarchy could discourage/slow down some refactoring.

2 cents

A.


#5

On May 25, 7:24 am, Andy F removed_email_address@domain.invalid wrote:

Generally I think using nested classes for real helper classes that can conceptually only be for use with the parent class is a useful way of avoiding namespace clutter.

+1

This is the only really good reason I’ve found for doing so.

On very rare occasion, when I had only one term in mind for both a
namespace and a base class, this has seemed useful:

class BaseClass

class SubClass < self
end

end

The fact hat the namespace is a class rather than a module is
inconsequential. In fact, I remain of the opinion that Ruby would be
better if Class and Module were not distinct.

T.


#6

On Mon, May 25, 2009 at 8:53 AM, trans removed_email_address@domain.invalid wrote:

On May 25, 7:24 am, Andy F removed_email_address@domain.invalid wrote:

Generally I think using nested classes for real helper classes that can conceptually only be for use with the parent class is a useful way of avoiding namespace clutter.

This is the only really good reason I’ve found for doing so.

I can’t agree with that, the value of namespaces is orthogonal to
ideas like ‘private’ classes, in fact, I think it’s more valuable when
the names are intended to be used outside of the implementation of a
class, it helps whenever two things end up competing for a name.

For example in my new icalendar gem, I use nested name spacing so that
I can have an Event class, and a using application can have it’s own
Event class(es), maybe one might be a database model.

I’ve seen, and been involved with too many languages which suffered
from the lack of Namespaces, sometimes adding them in later versions
of the language, not to appreciate the value.

It really isn’t an issue of containing a class within a class, it’s an
issue of containing names within name spaces.

And I do other things like putting a module which I’ve used to
refactor a large class into separate files inside the namespace of the
(main or only) class which includes it.
http://github.com/rubyredrick/ri_cal/tree/master


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale


#7

I sometimes use nested classes to avoid namespace clutter. The only
downsides I found are related to inheritance, in particular when you
split out classes into different files.

[a.rb]
require ‘a/b’
class A < SuperClass
end

[a/b.rb]
class A < SuperClass
class B
end
end

In both files you have to have the correct superclass (which can be
hard during refactoring). There are different ways to construct this,
however:

[a.rb]
class A < SuperClass
require ‘a/b’
end

[a/b.rb]
class A::B
end

The downside of this is that ‘a/b.rb’ can’t be required on it’s own.


#8

On May 25, 9:47 am, Rick DeNatale removed_email_address@domain.invalid wrote:

class, it helps whenever two things end up competing for a name.

For example in my new icalendar gem, I use nested name spacing so that
I can have an Event class, and a using application can have it’s own
Event class(es), maybe one might be a database model.

I’m not seeing how you disagree. The example you give is seems like a
fair example of the reason stated. I take it you have an ICalendar
class as the top namespace? Then Event is being used by it, even if in
a round about way --and even if the class could be used independently,
it was designed for use in this context.

I’ve seen, and been involved with too many languages which suffered
from the lack of Namespaces, sometimes adding them in later versions
of the language, not to appreciate the value.

It really isn’t an issue of containing a class within a class, it’s an
issue of containing names within name spaces.

Sure, but the question translates to Ruby as a question of practice,
i.e. typically one should use modules for name spaces, and hence the
question arises, when is using a class as a name space a better idea?

And I do other things like putting a module which I’ve used to
refactor a large class into separate files inside the namespace of the
(main or only) class which includes it.http://github.com/rubyredrick/ri_cal/tree/master

That’s cool. Your making class components. Still falls well into the
stated reason --the class is making use of the modules.

T.


#9

On Tue, May 26, 2009 at 10:38 AM, Simon C.
removed_email_address@domain.invalid wrote:

class A < SuperClass
require ‘a/b’
end

[a/b.rb]
class A::B
end

The downside of this is that ‘a/b.rb’ can’t be required on it’s own.

Sounds like a job for Ruby’s not-well-enough-known Module#autoload

http://talklikeaduck.denhaven2.com/2009/04/06/all-that-you-might-require


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale


#10

2009/5/26 Simon C. removed_email_address@domain.invalid:

class A < SuperClass
require ‘a/b’
end

[a/b.rb]
class A::B
end

The downside of this is that ‘a/b.rb’ can’t be required on it’s own.

IMHO this is not a problem of inheritance but of clear priority: class
A should be defined in one primary file. All other files that
modify it (i.e. by adding method or whatnot) should require that
primary file and reopen the class to do whatever they need.

So, basically the layout should look like this:

[a.rb]
class A < SuperClass
def method_of_A_which_does_not_use_B
end
end

[a/b.rb]
require ‘a’

class A
class B
end

def method_of_A_which_uses_B
end
end

Actually, if you use A only for namespace handling then a module would
probably a better thing to have here. Other than that, if A’s
implementation needs A::B to work, then splitting both out into two
files does not make much sense.

Kind regards

robert


#11

On May 25, 2009, at 03:40, Mike S. wrote:

Do you ever use this? Can you see a reason why it doesn’t seem to be
favoured?

I use it all the time, and it is highly favored. It’s common in the
standard library. Resolv, RDoc, RubyGems, Net::HTTP, …