ruby系列教材(22):Implementing SongList

上一篇 / 下一篇  2008-02-02 15:23:24 / 个人分类:Ruby

举例来巩固一下前面学习的成果,让我们来实现播放器的播放列表(SongList):

 

append(song)→ list

为list添加一首歌,添加在首位置,并且返回这个list

 

delete_first()→ song

删除第一首歌,并返回这首歌

 

delete_last()→ song

删除最后一首歌,并返回这首歌

 

[index]→ song

工具index来返回一种index指定的song

 

with_title(title)→ song

通过song的title,反正这个指定的song

 

我们可以看到,SongList可以在首位置添加一首歌,可以删除首位置的一首歌,可以删除末位的一首歌,由此我们应该是用dequeue这个数据结构来实现这个功能:

dequeue:double ended queue

 

这些本不是ruby的内容,但是我相信大家应该不会为此而吝惜时间,stacks,queues,dequeues都是有序排列成的,这个区别于sets的一个重要特点,hashes也是无序的,所谓的无序是items或者说elements的顺序

1)stack:LIFO,后进先出,进入方式是压栈,从top压入,出栈弹出最上item

2)queue:FIFI,先进先出,进入方式是从bottom进入,出栈弹出最上的item

3)dequeue:前后(top,bottom)都可以进出item

 

 

继续我们的implementing SongList之旅

ruby里面提供了丰富的方法,在对于array这个class时,提供了一些方法,使得这个array变成一个stack,queue或者dequeue,这样的方式比java灵活,使用java如何实现?用interface,这就使得我们必须去关心实现。利用array我们可以实现很多功能

 

initialize:

class SongList

  def initialize

    @songs = Array.new

  end

end

这里为SongList建立一个用于保存song的array

 

 

append:

class SongList

  def append(song)

    @songs.push(song)     #push为array尾部添加一个element

    self                               #同于return self ,self 表示返回一个自己(这个method所在的class)的object,这里就是SongList的object

  end

end

 

这里希望大家不要去思考array class 的method到底是把array变成了什么样的数据结构,只要关系这个method对array做了什么事情,就可以了

 

delete:

class SongList

  def delete_first

    @songs.shift

  end

  def delete_last

    @songs.pop

  end

end

 

 

下面是特殊的方法:[]

class SongList

  def [](index)            #定义[]方法,使用这样的规则

    @songs[index]

  end

end

 

 

 

对于array methods总结:

methodsparametersreturn
pushallarray
shiftobj or nil
popobj or nil

shift删除数组第一个element,然后返回这个element

pop删除数组最后一个element,然后返回这个element

 

 

最后说明一下:ClassName#method_name 这说明class有method_name 这个method,比如:

Array#shift 这个说明Array这个class有shift这个method。在你参考library或者一些文章的时候,可能看到这样的表达,这里告诉大家一下

 

 

我们实现到这里,不想再做复杂的实现过程,现在学习任何测试

Unit testing:ruby为我们提供了一个testing framework,在这个framework里面有2个比较重要的方法:

assert_equal:带2个parameters,判断这2个parameters是不是相等,假如不相等,产生failures

assert_nil:带1个parameter,判断这个parameter是不是nil,假如不等于nil,产生failures

 

 

代码:

require 'test/unit'
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

 

 

完整代码下载

 

测试正确:

-------------------------------------------------------

Loaded suite D:/Ruby-1
Started
.
Finished in 0.0 seconds.

1 tests, 8 assertions, 0 failures, 0 errors
-------------------------------------------------------

 

 

出错:

-------------------------------------------------------

Loaded suite D:/Ruby-1
Started
F
Finished in 0.03 seconds.

  1) Failure:
test_delete(TestSongList) [D:/Ruby-1.rb:47]:
<#<Song:0x2ba9fe4 @artist="artist3", @no=3, @title="title3">> expected but was
<#<Song:0x2ba9fa8 @artist="artist4", @no=4, @title="title4">>.

1 tests,6 assertions, 1 failures, 0 errors

-------------------------------------------------------

这里给出信息得到在第7个assertion处出现了问题,注意不需要使用new产生TestSongList,直接运行就好了,因为test包含了initial housekeeping,它会通知ruby,要使用TestUnit framework,并且告诉framework我们已经写了测试代码


TAG: Ruby

 

评分:0

我来说两句

我的栏目

日历

« 2024-05-10  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 22933
  • 日志数: 47
  • 建立时间: 2008-01-29
  • 更新时间: 2008-02-02

RSS订阅

Open Toolbar