Menu
CoddyTech

to_s 和 inspect

本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 5 课,共 57 课。

puts 会通过调用对象的 to_s 方法将对象转换为文本。默认的 to_s 只会给出类名和内存地址,例如 #<Book:0x000055d0>,所以类会定义自己的 to_s。字符串插值也会调用 to_s:

class Book
  def initialize(title, pages)
    @title = title
    @pages = pages
  end

  def to_s
    "#{@title} (#{@pages} pages)"
  end
end

book = Book.new("Dune", 412)
puts book
puts "Reading #{book}"

输出:

Dune (412 pages)
Reading Dune (412 pages)

join 也会对每个元素调用 to_s,所以对象数组会按你定义的格式打印:

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

  def to_s
    @title.upcase
  end
end

shelf = [Book.new("Dune"), Book.new("Emma")]
puts shelf.join(", ")
puts "Shelf: #{shelf.join(" / ")}"

输出:

DUNE, EMMA
Shelf: DUNE / EMMA

p 适合程序员使用:它会打印 inspect,以明确无误的方式显示一个值。字符串会保留引号,nil 也会显示出来。对于你自己的对象,默认的 inspect 会列出实例变量:

p "Dune"
puts "Dune"
p [1, "a", nil]
puts [1, "a", nil].inspect

输出:

"Dune"
Dune
[1, "a", nil]
[1, "a", nil]

重写 inspect,以便在调试时获得简短、准确的描述。p 和数组的 inspect 会使用它,而 puts 仍会使用 to_s:

class Point
  def initialize(x, y)
    @x = x
    @y = y
  end

  def to_s
    "(#{@x}, #{@y})"
  end

  def inspect
    "#<Point x=#{@x} y=#{@y}>"
  end
end

pt = Point.new(1, 2)
puts pt
p pt
p [pt, Point.new(0, 5)]

输出:

(1, 2)
#<Point x=1 y=2>
[#<Point x=1 y=2>, #<Point x=0 y=5>]
challenge icon

挑战

简单

完成 Track 类。initialize(title, artist, seconds) 会存储这些值。to_s 返回 Dune by Ada (3:05),时长以分钟和两位数秒数表示;inspect 返回 #<Track "Dune" 185s>,标题用双引号括起来。

提供的代码会读取格式为 title,artist,seconds 的曲目行,用 puts 打印每首曲目,然后用 p 打印整个列表。

你的代码写在 track.rb 中。main.rb 包含提供的输入和输出代码,不能修改。

亲手试试

require_relative 'track'

# 提供的输入输出代码:保持原样
input = []
while (line = gets)
  input << line.chomp
end
tracks = input.map do |line|
  title, artist, seconds = line.split(",")
  Track.new(title, artist, seconds.to_i)
end
tracks.each { |t| puts t }
p tracks
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Ruby 在线编译器