Menu
CoddyTech

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

Часть раздела Объектно-ориентированное программирование путешествия по 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

Выражение присваивания всегда возвращает значение в его правой части, а не то, что возвращает или сохраняет сеттер. Чтобы увидеть сохранённое значение, прочитайте атрибут ещё раз:

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