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

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

你可能感兴趣的:(Ruby学习笔记4,实现Song和SongList类及其单元测试)