Menu
CoddyTech

自定义设置器

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

setter 是一种名称以 = 结尾的方法。自己编写 setter,而不是使用 attr_writer,可以在存储值之前先对其进行清理:

class Person
  attr_reader :name

  def name=(value)
    @name = value.strip.capitalize
  end
end

ada = Person.new
ada.name = "   aDA  "
puts "[#{ada.name}]"

输出:

[Ada]

setter 也可以通过引发错误来拒绝一个值。只有当值通过检查时,实例变量才会被赋值,因此对象会保留原来的状态:

class Product
  attr_reader :price

  def initialize(price)
    @price = price
  end

  def price=(value)
    raise ArgumentError, "price must be positive, got #{value}" if value <= 0

    @price = value
  end
end

item = Product.new(10)
begin
  item.price = -5
rescue ArgumentError => e
  puts e.message
end
puts item.price

输出:

price must be positive, got -5
10

赋值表达式总是返回其右侧的值,而不是 setter 返回或存储的值。再次读取属性,查看存储的值:

class Thermometer
  attr_reader :celsius

  def celsius=(value)
    @celsius = value.round
  end
end

t = Thermometer.new
result = (t.celsius = 21.7)
puts result
puts t.celsius

输出:

21.7
22

读取器和自定义设置器一起提供一个属性,外部代码可以读取和更改它,但只能设置为有效值。只在设置器中进行检查,这样每次更改都会遵循同一规则:

class Volume
  attr_reader :level

  def level=(value)
    raise ArgumentError, "level must be 0-10" unless (0..10).cover?(value)

    @level = value
  end
end
challenge icon

挑战

简单

完成 Person 类。它的 setter name= 会去除值两端的空格,并将每个单词的首字母大写( ada lovelace 会变成 Ada Lovelace)。当年龄不在 0 到 150 之间时,它的 setter age= 会抛出 ArgumentError,并显示消息 invalid age: 200;否则会存储该值。两个值都可以读取。

新建的 Person 的名字为 Unknown,年龄为 0。提供的代码会读取 name text 或 age n 命令,通过 setter 应用这些命令,并在每条命令后将此人打印为 Ada Lovelace (36);如果 setter 拒绝该值,则打印错误消息。

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

亲手试试

require_relative 'person'

# 提供的输入/输出代码:保持原样。
input = []
while (line = gets)
  input << line.chomp
end
person = Person.new
input.each do |line|
  command, value = line.split(" ", 2)
  begin
    command == "name" ? person.name = value : person.age = value.to_i
    puts "#{person.name} (#{person.age})"
  rescue ArgumentError => e
    puts e.message
  end
end
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Ruby 在线编译器