Forum: Ruby Do you nest classes inside classes?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Mike S. (Guest)
on 2009-05-25 14:40
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?
James C. (Guest)
on 2009-05-25 14:48
(Received via mailing list)
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.
Pascal J. Bourguignon (Guest)
on 2009-05-25 15:16
(Received via mailing list)
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.
Andy F (Guest)
on 2009-05-25 15:25
(Received via mailing list)
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.
Thomas S. (Guest)
on 2009-05-25 16:54
(Received via mailing list)
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.
Rick D. (Guest)
on 2009-05-25 17:48
(Received via mailing list)
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
Thomas S. (Guest)
on 2009-05-26 09:06
(Received via mailing list)
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.
Simon C. (Guest)
on 2009-05-26 18:38
(Received via mailing list)
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.
Rick D. (Guest)
on 2009-05-26 18:50
(Received via mailing list)
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-...


--
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
Eric H. (Guest)
on 2009-05-27 00:56
(Received via mailing list)
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, ...
Robert K. (Guest)
on 2009-05-27 11:45
(Received via mailing list)
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
This topic is locked and can not be replied to.