一首Song的信息包括歌名,作者,長度,這些信息在構(gòu)造函數(shù)里設(shè)置
class Song
def initialize(name, artist, duration)
@name = name
@artist = artist
@duration = duration
end
end
為所有的屬性加上Getter和Setter
attr_reader :name, :artist, :duration
attr_writer :name, :artist, :duration
重載to_s方法,輸出描述性更好的信息
def to_s
"Song: #@name--#@artist (#@duration)"
end
定義Song的一個(gè)子類KaraokeSong,KaraokeSong比Song就多出了lyrics屬性
class KaraokeSong < Song
attr_reader :lyrics
attr_writer :lyrics
def initialize(name, artist, duration, lyrics)
super(name, artist, duration)
@lyrics = lyrics
end
end
重載to_s方法,加上lyrics屬性
def to_s
super + " [#@lyrics]"
end
SongList是一個(gè)Song的容器,而非Song的一個(gè)子類,所以內(nèi)部用數(shù)組保存Songs,即SongList使用Song類,兩者是Composite的關(guān)系,而非繼承關(guān)系
class SongList
def initialize
@songs = Array.new
end
end
SongList要提供方法以便加入,刪除,取回,查找Song。Append方法加入一首歌
def append(song)
@songs.push(song)
self
end
這里不使用筆記3里面介紹的Index操作,而用Ruby Array類的方法push,push將參數(shù)插在尾部。self相當(dāng)于Java和C++中的this,append返回當(dāng)前對(duì)象,以便函數(shù)調(diào)用鏈的編寫,比如 list.append(song1).append(song2).
刪除頭部和尾部的實(shí)現(xiàn)
def delete_first
@songs.shift
end
def delete_last
@songs.pop
end
shift將第二個(gè)到最后一個(gè)元素向右移了一位,即刪除了第一個(gè)元素,返回被刪的元素。pop類似于shift,只不過是針對(duì)最后一個(gè)元素。
下一個(gè)要實(shí)現(xiàn)的方法是取回Song,這里用[ ]
def [](index)
@songs[index]
end
寫了這么多,我們?cè)搶懥藛卧獪y(cè)試了,Ruby自帶了一個(gè)測(cè)試框架TestUnit。測(cè)試類要從Test::Unit::TestCase繼承,并且需要加入test/unit模塊。測(cè)試類最好定義不同的文件里,所以還要加入定義類的文件,這里假設(shè)早前的3個(gè)類定義在songs/song.rb文件里。
require 'test/unit'
require 'songs/song.rb'

class TestSongList < Test::Unit::TestCase
def test_delete
list = SongList.new
s1 = Song.new('title1', 'artist1', 1)
s2 = Song.new('title2', 'artist2', 2)
s3 = Song.new('title3', 'artist3', 3)
s4 = Song.new('title4', 'artist4', 4)
list.append(s1).append(s2).append(s3).append(s4)
assert_equal(s1, list[0])
assert_equal(s3, list[2])
assert_nil(list[9])
assert_equal(s1, list.delete_first)
assert_equal(s2, list.delete_first)
assert_equal(s4, list.delete_last)
assert_equal(s3, list.delete_last)
assert_nil(list.delete_last)
end
end
下面來實(shí)現(xiàn)查找with_title(title), 返回name為title的song,或者nil,如果沒有。可以用for循環(huán)遍歷songs,比較每個(gè)song。實(shí)際上Array::find已經(jīng)為我們寫好了for循環(huán)結(jié)構(gòu),find方法需要一段判斷一個(gè)song是否滿足要求的代碼,即name是否相等。
def with_title(title)
@songs.find { |song| song.name == title }
end
同時(shí)寫好with_title的單元測(cè)試
def test_with_title
list = SongList.new
s1 = Song.new('title1', 'artist1', 1)
s2 = Song.new('title2', 'artist2', 2)
s3 = Song.new('title3', 'artist3', 3)
s4 = Song.new('title4', 'artist4', 4)
list.append(s1).append(s2).append(s3).append(s4)
assert_equal(s1, list.with_title("title1"))
assert_equal(s2, list.with_title("title2"))
assert_equal(s3, list.with_title("title3"))
assert_equal(s4, list.with_title("title4"))
assert_nil(list.with_title("title5"))
end
轉(zhuǎn)載請(qǐng)保留
http://m.tkk7.com/xilaile/archive/2007/05/07/115645.html