Created
October 24, 2009 17:58
-
-
Save rklemme/217641 to your computer and use it in GitHub Desktop.
Complete file for blog entry "The Complete Class"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'yaml' | |
Track = Struct.new :title, :duration | |
# An Album represents an audio medium which has title, | |
# interpret, a pause duration between tracks and a list | |
# of individual tracks. | |
class Album | |
attr_reader :title, :interpret, :pause | |
# initialization | |
def initialize(title, interpret, pause = 0) | |
super() | |
# main properties | |
self.title = title | |
self.interpret = interpret | |
@tracks = [] | |
# additional properties | |
self.pause = pause | |
# redundant properties | |
# left out | |
end | |
def title=(t) | |
@title = t.dup.freeze | |
end | |
def interpret=(i) | |
@interpret = i.dup.freeze | |
end | |
def pause=(time) | |
@pause = time | |
@duration = nil | |
end | |
def each_track(&b) | |
@tracks.each(&b) | |
self | |
end | |
def add_track(tr) | |
@tracks << tr | |
@duration = nil | |
self | |
end | |
def clear_tracks | |
@tracks.clear | |
@duration = nil | |
self | |
end | |
alias << add_track | |
def tracks | |
@tracks.dup | |
end | |
def duration | |
@duration ||= @tracks.empty? ? | |
0 : | |
@tracks.inject(-pause) do |sum, tr| | |
sum + pause + tr.duration | |
end | |
end | |
# conversion to a printable string | |
def to_s | |
"Album '#{title}' by '#{interpret}' (#{tracks.size} tracks)" | |
end | |
# equivalence | |
def eql?(album) | |
self.class.equal?(album.class) && | |
title == album.title && | |
interpret == album.interpret && | |
tracks == album.tracks | |
end | |
alias == eql? | |
# hash code calculation | |
def hash | |
title.hash ^ | |
interpret.hash ^ | |
tracks.hash | |
end | |
# comparability | |
include Comparable | |
def <=>(o) | |
self.class == o.class ? | |
(interpret <=> o.interpret).nonzero? || | |
(title <=> o.title).nonzero? || | |
(tracks <=> o.tracks).nonzero? || | |
(pause <=> o.pause) || | |
0 : | |
nil | |
end | |
# cloning | |
def initialize_copy(source) | |
super | |
@tracks = @tracks.dup | |
end | |
# freezing | |
def freeze | |
# unless frozen? | |
@tracks.freeze | |
duration | |
# end | |
super | |
end | |
# customized persistence | |
def marshal_dump | |
a = (super rescue []) | |
a.push(@title, @interpret, @pause, @tracks) | |
end | |
def marshal_load(dumped) | |
super rescue nil | |
@title, @interpret, @pause, @tracks = *dumped.shift(4) | |
end | |
def to_yaml_properties | |
a = super | |
a.delete :@duration | |
a | |
end | |
# matching | |
def ===(track) | |
t = (track.title rescue track) | |
tracks.find {|tr| t == tr.title} | |
end | |
def =~(rx) | |
rx =~ title | |
end | |
end | |
# ===== Test Code =================================================== | |
alb = Album.new "In through the out door", "Led Zeppelin", 2 | |
printf "%-30s %p\n", 'empty album', alb | |
alb << Track.new("In the Evening", 6 * 60 + 49) | |
alb << Track.new("South Bound Saurez", 4 * 60 + 12) | |
alb << Track.new("Fool in the Rain", 6 * 60 + 12) | |
alb << Track.new("Hot Dog", 3 * 60 + 17) | |
printf "%-30s %p\n", 'page 1 completed', alb | |
printf "%-30s %p\n", 'duration', alb.duration | |
printf "%-30s %p\n", 'after duration calculation', alb | |
page1 = alb.dup | |
printf "%-30s %p\n", 'copy of page 1', page1 | |
printf "%-30s %p\n", 'copy equivalent?', alb == page1 | |
printf "%-30s %p\n", 'really?', page1 == alb | |
alb << Track.new("Carouselambra", 10 * 60 + 32) | |
alb << Track.new("All my Love", 5 * 60 + 51) | |
alb << Track.new("I'm gonna crawl", 5 * 60 + 30) | |
alb.duration | |
printf "%-30s %p\n", 'full album', alb | |
printf "%-30s %p\n", 'page 1', page1 | |
printf "%-30s %p\n", 'track found?', alb === "All my Love" | |
printf "%-30s %p\n", 'track on page 1', page1 === "All my Love" | |
puts alb, page1 | |
2.times { alb.freeze } | |
printf "%-30s %p\n", 'full album', alb | |
alb2 = Marshal.load(Marshal.dump(alb)) | |
printf "%-30s %p\n", 'marshaled', alb2 | |
alb3 = YAML.load(YAML.dump(alb)) | |
printf "%-30s %p\n", 'yamld', alb3 | |
printf "%-30s %p\n", 'yamld duration', alb3.duration |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment