Hi,
I’m reading the online eBook of Programming Ruby, it’s an excellent
resource for learning Ruby.
I am having some trouble understanding the KaraokeSong#to_s example.
Quoting the text:
"
class KaraokeSong
…
def to_s
“KS: #{@name}–#{@artist} (#{@duration}) [#{@lyrics}]”
end
end
aSong = KaraokeSong.new(“My Way”, “Sinatra”, 225, “And now, the…”)
aSong.to_s » “KS: My Way–Sinatra (225) [And now, the…]”
We’re correctly displaying the value of the |@lyrics| instance variable.
To do this, the subclass directly accesses the instance variables of its
ancestors. So why is this a bad way to implement |to_s|? The answer has
to do with good programming style (and something called /decoupling/).
By poking around in our parent’s internal state, we’re tying ourselves
tightly to its implementation. Say we decided to change |Song| to store
the duration in milliseconds. Suddenly, |KaraokeSong| would start
reporting ridiculous values. The idea of a karaoke version of ``My Way’’
that lasts for 3750 minutes is just too frightening to consider."
What does it mean by “the subclass directly accesses the instance
variables of its ancestors”? The Song class does not have the @lyrics
instance variable. And are @name, @artist, and @duration not instance
variables for the KaraokeSong class, so they have nothing to do with the
instance variables with the same name for the Song class? Even if I
change Song to store the duration in milliseconds, would not KaraokeSong
still store in minutes, because when I create a new KaraokeSong object,
I pass it the duration argument in minutes?
Perhaps an example of what could go wrong would help.
Dave T. kindly replied with the following:
“Classes don’t have instance variables: instances do. But classes
contain the code that uses instance variables. So, in this case, the
code that “knows about” @name (for example) is in the Song class. The
subclass should not assume this internal implementation. Instead, it
should use the interface provided by the Song class, in this case using
its to_s method.”
But I am still confused. OK, so the code that “knows about” @name, etc.
is in the Song class, but doesn’t the KaraokeSong class also know about
these instance variables? Since it super’d the initialize method?
Thanks to clear this up.
Regards,
Clifford L.