0

我一直在关注镐书中的代码示例,但最近被我的代码中的一个错误难住了。

添加这行代码后(在下面的完整文件中的~第 60 行)-

@index.add_to_index(song, song.name, song.artist)

我收到此错误:

Loaded suite ruby_juke
Started
E
Finished in 0.000213 seconds.

  1) Error:
test_delete(TestSongList):
NoMethodError: undefined method `name' for #<Song:0x10cd95eb0>
    ruby_juke.rb:60:in `append'
    ruby_juke.rb:163:in `test_delete'

1 tests, 0 assertions, 0 failures, 1 errors

我的问题是,那一行代码在做什么导致错误?

如果您可以提供帮助,请随时发送提示、提示链接、问我问题等。

谢谢!-d

ps 如果有帮助,这里是我的 ruby​​_juke.rb 程序的内容:

#!/usr/local/bin/ruby -w

class Song

  attr_writer :duration

  @@plays = 0

  def initialize(name, artist, duration)
    @name     = name
    @artist   = artist
    @duration = duration
    @plays    = 0
  end

  def play
    @plays  += 1   # same as @plays = @plays + 1
    @@plays += 1
    "this song: #@plays plays. total #@@plays plays."
  end

  def duration_in_minutes
    @duration/60.0    # force floating point
  end

  def duration_in_minutes=(new_duration)
    @duration = (new_duration*60).to_i
  end

  def to_s
    "song: #@name--#@artist (#@duration)"
  end

end

class KaraokeSong < Song

  def initialize(name, artist, duration, lyrics)
    super(name, artist, duration)
    @lyrics = lyrics
  end

  # format ourselves as a string by appending
  # our lyrics to our parent's #to_s value.
  def to_s
    super + " [#@lyrics]"
  end

end

class SongList

  def initialize
    @songs = Array.new
    @index = WordIndex.new
  end

  def append(song)
    @songs.push(song)
    @index.add_to_index(song, song.name, song.artist)
    self
  end

  def lookup(word)
    @index.lookup(word)
  end

  def delete_first
    @songs.shift
  end

  def delete_last
    @songs.pop
  end

  def [](index)
    @songs[index]
  end

  def with_title(title)
    @songs.find {|song| title == song.name }
  end

  MAX_TIME = 5*60        # 5 minutes

  def SongList.is_too_long(song)
    return song.duration > MAX_TIME
  end

end

class WordIndex

  def initialize
    @index = {}
  end

  def add_to_index(obj, *phrases)
    phrases.each do |phrase|
      phrase.scan(/\w[-w']+/) do |word|      # extract each word
        word.downcase!
        @index[word] = [] if @index[word].nil?
        @index[word].push(obj)
      end
    end
  end

  def lookup(word)
    @index[word.downcase]
  end

end

class MyLogger

  private_class_method :new

  @@logger = nil

  def MyLogger.create
    @@logger = new unless @@logger
    @@logger
  end

end

class Button

  def initialize(label)
    @label = label
  end

end

songlist = SongList.new

class JukeboxButton < Button

  def initialize(label, &action)
    super(label)
    @action = action
  end

  def button_pressed
    @action.call(self)
  end

end

start_button = JukeboxButton.new("Start") { songlist.start }
pause_button = JukeboxButton.new("Pause") { songlist.pause }


require 'test/unit'
class TestSongList < Test::Unit::TestCase

  def test_delete
    list = SongList.new
    s1 = Song.new('title1', 'artst1', 1)
    s2 = Song.new('title2', 'artst2', 2)
    s3 = Song.new('title3', 'artst3', 3)
    s4 = Song.new('title4', 'artst4', 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
4

2 回答 2

2

您的Song课程没有name方法(如错误所述)。您需要添加一个返回私有变量值的方法@name

于 2012-09-05T20:07:30.283 回答
2

你没有 getter 和 setter for name。例如

def name
 @name
end

def name=(name)
 @name = name
end

对所有要显式设置的属性执行此操作,而不是通过初始化程序。有一个捷径。attr_accessor. 阅读:http ://www.rubyist.net/~slagell/ruby/accessors.html

于 2012-09-05T20:13:18.937 回答