Arrays Ruby:列出数组中的所有项

Arrays Ruby:列出数组中的所有项,arrays,ruby,printing,Arrays,Ruby,Printing,我尝试了至少5种不同的方法,目前使用的是.each方法 我认为问题在于代码块底部的print_songs方法 我得到的错误是: Artist #print_songs lists all of the artist's songs Failure/Error: expect{artist.print_songs}.to output("Dirty Diana\nBillie Jean\n").to_stdout expected block to output "Dirt

我尝试了至少5种不同的方法,目前使用的是.each方法

我认为问题在于代码块底部的
print_songs
方法

我得到的错误是:

Artist #print_songs lists all of the artist's songs
     Failure/Error: expect{artist.print_songs}.to output("Dirty Diana\nBillie Jean\n").to_stdout
       expected block to output "Dirty Diana\nBillie Jean\n" to stdout, but output "#<Song:0x000000019757b0>\n#<Song:0x000000019756e8>\n"
       Diff:
       @@ -1,3 +1,3 @@
       -Dirty Diana
       -Billie Jean
       +#<Song:0x000000019757b0>
       +#<Song:0x000000019756e8>
答复:

def print_songs
  @songs.each{|song| puts song.name}
end

它正在按预期工作。让我们看看试过的。你能发布你试过的测试用例吗

a1 = Artist.create(name: 'Lana del re')
a1.add_song('Young and Beautiful')
a1.add_song('haunted')
a1.print_songs
["Young and Beautiful", "haunted"] #output assuming song as a String object 

很明显,这首歌可能不是一根弦,而是某种物体。将
to_s
方法添加到任何对象,puts都应该自动调用它,当然,您也可以手动调用

下面是我为证实这种行为所做的快速测试

irb(main):001:0> class Song
irb(main):002:1> def initialize(title)
irb(main):003:2> @title = title
irb(main):004:2> end
irb(main):005:1> end
=> :initialize
irb(main):006:0> s = Song.new "scarborough fair"
=> #<Song:0x0000000030bb78 @title="scarborough fair">
irb(main):007:0> puts s
#<Song:0x0000000030bb78>
=> nil
irb(main):008:0> class Song
irb(main):009:1> def to_s
irb(main):010:2> return @title
irb(main):011:2> end
irb(main):012:1> end
=> :to_s
irb(main):013:0> puts s
scarborough fair
=> nil
irb(main):014:0>
irb(main):001:0>课堂歌曲
irb(主):002:1>def初始化(标题)
irb(主):003:2>@title=title
irb(主):004:2>结束
irb(主):005:1>结束
=>:初始化
irb(main):006:0>s=Song.new“斯卡伯勒集市”
=> #
irb(主):007:0>s
#
=>零
irb(主):008:0>课堂歌曲
irb(主):009:1>def至
irb(主要):010:2>返回@title
irb(主):011:2>结束
irb(主):012:1>结束
=>:至
irb(主要):013:0>s
斯卡伯勒集市
=>零
irb(主要):014:0>
编辑:

但这是为什么呢?
简言之,当您创建一些自定义对象类时,比如上面示例中的
Song
,Ruby不知道如何将其表示为字符串。默认的
to_s
方法只是输出类和对象ID,这对于调试来说是可以的,但是如果有某种明显的方法将对象表示为字符串,比如
Song
(人们会期望Song.to_s返回歌曲标题),必须重写默认的to_s方法,或者包含/继承另一个类/模块,该类/模块具有更合适的
to_s
实现。默认情况下,调用
to_s
打印对象的类名和对象id的编码,如下所示:
“#”
。也就是说,您需要覆盖
歌曲
类上的
to_s
方法:

class Song
  def initialize(title)
    @title = title
  end

  def to_s
    @title
  end
end
def print_songs
  puts @songs.each(&:to_s)
end
然后,您需要在现有的
Artist
类上相应地修改
print_songs
方法:

class Song
  def initialize(title)
    @title = title
  end

  def to_s
    @title
  end
end
def print_songs
  puts @songs.each(&:to_s)
end
each(&:to_s)
位基本上调用传递到块的每个
Song
对象上的
to_s
方法,这与

def print_songs
  puts @songs.each { |song| song.to_s }
end
这也可以改写为

def print_songs
  puts @songs
end

在这种情况下,
put
会隐式地调用
@songs

元素上的
to_s
方法。您可以发布针对该代码运行的测试吗?我在本地测试了它,它按预期工作-即
print_songs
打印了添加到我创建的艺术家的所有歌曲。@alexnewby什么是
歌曲
?仅仅是一个
字符串
?在您的测试中,一首
歌曲
似乎是某种对象,因此当您打印歌曲时,您打印的是歌曲对象,而不是歌曲名称的字符串。“我已经尝试了至少5种不同的方法”—以这种方式处理问题将掩盖实际的错误。如果它曾经工作过“一百万次”,那么显然还有其他的问题。你必须修正它。好的,这首歌是一个物体。当我打印song.to_时,它仍然不起作用。不确定这是否应该是评论而不是回答。它并没有真正解决问题,但确认了OPs的声明:它应该工作。为什么song.to_不工作?为什么我需要为_s创建一个新方法?@alexnewby默认情况下,对_s的调用打印对象的类和对象id的编码,如下所示:
“#”
。要更改此方法,必须将
重写为部分不正确的方法;puts已经负责在非字符串对象上调用
to_s
,所以一旦定义了Song.to_s,您就可以执行
put-instance_of_-Song
,它会工作得很好(请参阅我的答案,我在irb中就是这么做的)@DarkWiiPlayer好的调用,我应该记得这个特性