On Mon, 13 Nov 2006, jan aerts (RI) wrote: > 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. 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 -- my religion is very simple. my religion is kindness. -- the dalai lama