gr8vyguy@Blogjava

Ruby学习笔记4,实现Song和SongList类及其单元测试

一首Song的信息包括歌名,作者,长度,这些信息在构造函数里设置

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的一个子类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是一个Song的容器,而非Song的一个子类,所以内部用数组保存Songs,即SongList使用Song类,两者是Composite的关系,而非继承关系
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将参数插在尾部。self相当于Java和C++中的this,append返回当前对象,以便函数调用链的编写,比如 list.append(song1).append(song2).

删除头部和尾部的实现
  def delete_first
    @songs.shift
  end
  
  
def delete_last
    @songs.pop
  end
shift将第二个到最后一个元素向右移了一位,即删除了第一个元素,返回被删的元素。pop类似于shift,只不过是针对最后一个元素。

下一个要实现的方法是取回Song,这里用[ ]
  def [](index)
    @songs[index]
  end

写了这么多,我们该写了单元测试了,Ruby自带了一个测试框架TestUnit。测试类要从Test::Unit::TestCase继承,并且需要加入test/unit模块。测试类最好定义不同的文件里,所以还要加入定义类的文件,这里假设早前的3个类定义在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

下面来实现查找with_title(title), 返回name为title的song,或者nil,如果没有。可以用for循环遍历songs,比较每个song。实际上Array::find已经为我们写好了for循环结构,find方法需要一段判断一个song是否满足要求的代码,即name是否相等。
  def with_title(title)
    @songs.find { 
|song| song.name == title }
  end

同时写好with_title的单元测试
  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


转载请保留http://www.blogjava.net/xilaile/archive/2007/05/07/115645.html

posted on 2007-05-06 17:32 gr8vyguy 阅读(626) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2007年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

公告

  • 转载请注明出处.
  • msn: gr8vyguy at live.com
  • 常用链接

    留言簿(9)

    随笔分类(68)

    随笔档案(80)

    文章分类(1)

    My Open Source Projects

    搜索

    积分与排名

    最新评论