Do you nest classes inside classes?

M

Mike Stephens

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 Fulton 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?
 
J

James Coglan

[Note: parts of this message were removed to make it a legal post.]

2009/5/25 Mike Stephens said:
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 Fulton 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.
 
P

Pascal J. Bourguignon

Mike Stephens said:
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 Fulton 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.
 
A

Andy F

Hi Mike,=0A=0ARuby and list noob here. Generally I think using nested class=
es for real helper classes that=A0can 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 go=
al 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 disc=
ourage/slow down some refactoring.=0A=0A2 cents=0A=0AA.
 
T

trans

Generally I think using nested classes for real helper classes that can c=
onceptually only be for use with the parent class is a useful way of avoidi=
ng 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.
 
R

Rick DeNatale

conceptually only be for use with the parent class is a useful way of avoid=
ing 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

--=20
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
 
T

trans

n conceptually only be for use with the parent class is a useful way of avo=
iding namespace clutter.
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'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_c=
al/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.
 
S

Simon Chiang

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.
 
R

Rick DeNatale

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

=A0[a.rb]
=A0require 'a/b'
=A0class A < SuperClass
=A0end

=A0[a/b.rb]
=A0class A < SuperClass
=A0 =A0class B
=A0 =A0end
=A0end

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

=A0[a.rb]
=A0class A < SuperClass
=A0 =A0require 'a/b'
=A0end

=A0[a/b.rb]
=A0class A::B
=A0end

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


--=20
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
 
E

Eric Hodel

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, ...
 
R

Robert Klemme

2009/5/26 Simon Chiang said:
I sometimes use nested classes to avoid namespace clutter. =A0The only
downsides I found are related to inheritance, in particular when you
split out classes into different files.

=A0[a.rb]
=A0require 'a/b'
=A0class A < SuperClass
=A0end

=A0[a/b.rb]
=A0class A < SuperClass
=A0 =A0class B
=A0 =A0end
=A0end

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

=A0[a.rb]
=A0class A < SuperClass
=A0 =A0require 'a/b'
=A0end

=A0[a/b.rb]
=A0class A::B
=A0end

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


--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top