Menu
CoddyTech

读取器与写入器

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

为每个实例变量编写读取方法会很重复。在类体中使用 attr_reader :title 会生成方法 title,它会返回 @title。一行可以列出多个名称:

class Book
  attr_reader :title, :pages

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

book = Book.new("Dune", 412)
puts book.title
puts book.pages

输出:

Dune
412

attr_writer :title 会生成一个setter(设置器),即方法 title=,它会将参数存储到 @title 中。Ruby 允许你使用赋值语法调用它:book.title = "Emma":

class Book
  attr_reader :title
  attr_writer :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("Dune")
book.title = "Dune Messiah"
puts book.title

输出:

Dune Messiah

attr_accessor 会同时生成读取器和设置器。有了这两者,+= 这样的简写也能使用,因为 player.score += 5 表示 player.score = player.score + 5:

class Player
  attr_accessor :name, :score

  def initialize(name)
    @name = name
    @score = 0
  end
end

ada = Player.new("Ada")
ada.score += 5
ada.score += 3
ada.name = "Ada L."
puts "#{ada.name}: #{ada.score}"

输出:

Ada L.: 8

尽量少暴露属性。对于外部代码可以读取但不能修改的值,使用 attr_reader;只有在设计上允许从外部修改值时,才添加 writer。给只有读取器的属性赋值会引发 NoMethodError:

class Book
  attr_reader :title

  def initialize(title)
    @title = title
  end
end

book = Book.new("Dune")
begin
  book.title = "Emma"
rescue NoMethodError => e
  puts e.message
end
puts book.title

输出:

undefined method `title=' for an instance of Book
Dune
challenge icon

挑战

简单

完成 Book 类。外部代码可以读取 title、author 和 pages,也可以读取和更改 pages_read,它的初始值为 0。progress 返回 Dune: 120/412 (29%),百分比向下取整。

提供的代码会根据输入的前三行(标题、作者、页数)创建一本书。之后的每一行都是读者读完的页数;代码会将每个数字加到 book.pages_read += n。最后,它会打印 Dune by Frank Herbert 和阅读进度。

你的代码写在 book.rb 中。main.rb 包含提供的输入/输出代码,不能编辑。

亲手试试

require_relative 'book'

# 提供的输入输出代码:保持原样
input = []
while (line = gets)
  input << line.chomp
end
book = Book.new(input[0], input[1], input[2].to_i)
input.drop(3).each { |n| book.pages_read += n.to_i }
puts "#{book.title} by #{book.author}"
puts book.progress
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Ruby 在线编译器