# Classes within classes

**URL:** <https://www.ruby-forum.com/t/classes-within-classes/75793>\
**Category:** Ruby\
**Created:** [November 13, 2006, 3:53pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793 "2006-11-13T15:53:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 3:53pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/1 "2006-11-13T15:53:01Z")

</div>

Hi all,

I’m trying to create a little library for drawing my data using SVG. One  
of the inherent properties of the drawings that I have to make, is that  
each picture can contain one or more tracks with each track containing  
one or more features (see ASCII art below).

±---------------------------picture-+  
| ±---------------------track1----+ |  
| | | |  
| | x x | |  
| | x x | |  
| | | |  
| | | |  
| ±-------------------------------+ |  
| |  
| ±---------------------track2----+ |  
| | | |  
| | xx | |  
| ±-------------------------------+ |  
±-----------------------------------+

As a track can _only_ be defined within a picture, and a feature can  
_only_ be defined within a track, I have set up the classes as follows:  
class Picture  
class Track  
class Feature  
end  
end  
end

The problem is that some of the properties of a Picture object have to  
be readable for its Track objects. This is _not_ simple inheritance,  
because Picture and Picture::Track are two completely different things.  
As I see it, there are several options:  
(A) either pass those properties as arguments every time you create a  
new Picture::Track object. Not optimal, because the same piece of data  
is copied over and over again.  
(B) set those features as global variables. Not optimal as well.  
© something more elegant?

More elaborately (showing some of the key features)  
  
class Picture  
def initialize(width)  
@width = width  
@tracks = Array.new  
end  
attr\_accessor :width, :tracks

def add\_track(name)  
@tracks.push(Picture::Track.new(name)  
return @tracks[-1]  
end

class Track  
# DO NOT CALL INITIALIZE METHOD DIRECTLY: use Picture#add\_track  
def initialize(name)  
@name = name  
end  
attr\_accessor :name

```
 def to_svg
   # I NEED THE WIDTH OF THE PICTURE HERE
   return

```

some\_xml\_that\_includes\_the\_width\_which\_was\_defined\_in\_Picture  
end

```
 class Feature
   ...
 end

```

end  
end  
\</LIB CODE SNIPPET\>

p = Picture.new(800) # Creates a new picture of 800pt width. p.add\_track('first\_track') p.add\_track('second\_track')

In the end, the question is: should I make Picture#width a global  
variable, should I add width as an argument to  
Picture::Track#initialize, or is there a more elegant solution? (I hope  
it’s the last one…)

Any help would be very much appreciated,  
jan.

Dr Jan Aerts  
Bioinformatics Group  
Roslin Institute  
Roslin, Scotland, UK  
+44 131 527 4200

---------The obligatory disclaimer--------  
The information contained in this e-mail (including any attachments) is  
confidential and is intended for the use of the addressee only. The  
opinions expressed within this e-mail (including any attachments) are  
the opinions of the sender and do not necessarily constitute those of  
Roslin Institute (Edinburgh) (“the Institute”) unless specifically  
stated by a sender who is duly authorised to do so on behalf of the  
Institute.

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 4:05pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/2 "2006-11-13T16:05:06Z")

</div>

On 11/13/06, jan aerts (RI) [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> | | x x | |
> 
> be readable for its Track objects. This is _not_ simple inheritance,  
> class Picture
> 
> some\_xml\_that\_includes\_the\_width\_which\_was\_defined\_in\_Picture  
> p = Picture.new(800) # Creates a new picture of 800pt width.  
> jan.  
> Hi,

two ideas:

1. pass the picture (it)self to the Track constructor and then query  
whatever you need
2. have all the svg generating stuff in another class that will be  
given the Picture object, and will iterate through it, creating the  
xml along the way (ERB template comes to my mind…)

Jan

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 4:39pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/3 "2006-11-13T16:39:14Z")

</div>

On Mon, 13 Nov 2006, jan aerts (RI) wrote:

> | | x x | |
> 
> be readable for its Track objects. This is _not_ simple inheritance,  
> because Picture and Picture::Track are two completely different things.  
> As I see it, there are several options:  
> (A) either pass those properties as arguments every time you create a  
> new Picture::Track object. Not optimal, because the same piece of data  
> is copied over and over again.

this is not true - ruby **always** passes references (unless you are  
seializing an object over a wire or to file) so there’s no harm in  
having a  
reference to a ‘parent’ object. in fact, given your spec, with all the  
‘_only_’ clauses, it makes perfect sense to design the nested classes as  
a  
factory chain, eg

class Picture  
def new\_track \*a, &b  
Track.new self, \*a, &b  
end

```
 class Track
   def initialize picture, *a, &b
     @picture = picture
   end

   def new_feature *a, &b
     Feature.new self, *a, &b
   end

   class Feature
     def initialize track, *a, &b
       @track = track
     end
   end
 end

```

end

so

picture = Picture.new

track = picture.new\_track :foo, :bar

feature = track.new\_feature :bar, :foo

this also has the nice feature that children prevent any required  
parents from  
having the gc evaporate them - so long as we have a reference up the  
object  
will not disappear. in fact, i’d probably setup the association as a  
two-way:

class Picture  
Tracks = []

```
 def new_track *a, &b
   t = Track.new self, *a, &b
 ensure
   Tracks << t
 end

 def each_track &b
   Tracks.each &b
 end

 class Track
   def initialize picture, *a, &b
     @picture = picture
   end

   Features = []

   def new_feature *a, &b
     f = Feature.new self, *a, &b
   ensure
     Features << f
   end

   def each_feature &b
     Features.each &b
   end

   class Feature
     def initialize track, *a, &b
       @track = track
     end
   end
 end

```

end

etc.

-a

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 4:51pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/4 "2006-11-13T16:51:16Z")

</div>

> > | | x x | |
> 
> ```
> t = Track.new self, *a, &b
> @picture = picture
> def each_feature &b
> 
> ```
> 
> etc.

Thanks. You really made that easy for me…

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 4:41pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/5 "2006-11-13T16:41:15Z")

</div>

> > | | x x | |
> > 
> > ```
> > attr_accessor :name
> > 
> > ```
> > 
> > end  
> > variable, should I add width as an argument to  
> > stuff in another class that will be given the Picture object,  
> > and will iterate through it, creating the xml along the way  
> > (ERB template comes to my mind…)
> 
> Jan

Thanks for your swift reply, Jan.

I did look briefly at these two options, but didn’t go for them  
previously. However, passing the Picture object itself _might_ actually  
be the best solution. I suppose the code would then look something like:

class Picture  
def add\_track(self, name)  
@tracks.push(Picture::Track.new(self, name))  
end

class Track  
def initialize(picture, name)  
width = picture.width  
name = name  
end  
end  
end

I’ll probably go for this one…

jan.

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 7:15pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/6 "2006-11-13T19:15:53Z")

</div>

why can’t you just use inheritage and mixins? would that generate a  
worse  
design then what you currently have?

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 6:35pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/7 "2006-11-13T18:35:41Z")

</div>

On 13.11.2006 15:50, jan aerts (RI) wrote:

> | | x x | |
> 
> be readable for its Track objects. This is _not_ simple inheritance,  
> because Picture and Picture::Track are two completely different things.  
> As I see it, there are several options:  
> (A) either pass those properties as arguments every time you create a  
> new Picture::Track object. Not optimal, because the same piece of data  
> is copied over and over again.  
> (B) set those features as global variables. Not optimal as well.  
> © something more elegant?

Why don’t you just add a member “container” or “parent” to the Feature  
(and maybe also Track) so a Track knows all of its Features and the  
Features all know the Track that they are part of? That’s a common  
idiom for tree storage if you need to navigate both directions (from  
root to leaf and vice versa).

Another note: while I can see why you nest classes that might become a  
bit unreadable. Also it does not prevent any outside code from  
accessing class Track and Feature - basically just the names get more  
complex through the nesting. An alternative approach is to just define  
a module as namespace and nest all classes in it.

module PictureApp  
class Picture  
end

class Track  
end

class Feature  
end  
end

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![jan\_aerts\_SRI](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/8c91f0/32.png) [@jan\_aerts\_SRI](https://www.ruby-forum.com/u/jan_aerts_SRI)\
**Post date:** [November 13, 2006, 11:08pm UTC](https://www.ruby-forum.com/t/classes-within-classes/75793/8 "2006-11-13T23:08:54Z")

</div>

Paul I. wrote:

> why can’t you just use inheritage and mixins? would that generate a worse  
> design then what you currently have?

[http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.4](http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.4)

- notably the comments in Rule #1

While a C++ text, the idea is relevant - C++ multiple inheritance was  
used to implement mixins (Rule #2 in that article encourages that), and  
the same rules should apply to Ruby as well.

In fact, most of the uses of normal inheritance I see in Ruby code is to  
save you (a little) typing over composition, instead of overriding /  
implementing the parent’s methods. The latter is usually unnecessary  
because of dynamic typing and blocks.

David V.
