Menu
Coddy logo textTech

Пользовательские сеттеры

Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 8 из 57.

Сеттер — это метод, имя которого заканчивается на =. Написав его самостоятельно вместо использования 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]

Сеттер также может отклонить значение, вызвав ошибку. Переменной экземпляра присваивается значение только тогда, когда значение проходит проверку, поэтому объект сохраняет своё прежнее состояние:

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. Его сеттер name= удаляет пробелы вокруг значения и делает каждое слово начинающимся с заглавной буквы ( ada lovelace превращается в Ada Lovelace). Его сеттер age= вызывает ArgumentError с сообщением invalid age: 200, когда возраст находится за пределами диапазона от 0 до 150, а в остальных случаях сохраняет его. Оба значения можно прочитать.

Новый экземпляр Person создаётся с именем Unknown и возрастом 0. Предоставленный код считывает команды name text или age n, применяет их через сеттеры и после каждой команды выводит человека в виде Ada Lovelace (36) либо выводит сообщение об ошибке, когда сеттер отклоняет значение.

Ваш код должен находиться в 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