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