self в методах
Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 9 из 57.
Внутри метода name = value всегда создаёт локальную переменную, даже если у класса есть сеттер name=. Чтобы вызвать сеттер, укажите получатель: self.name = value:
class Player
attr_accessor :level
def initialize
@level = 1
end
def broken_level_up
level = level + 1
rescue NoMethodError
puts "level is a new local variable here, still nil"
end
def level_up
self.level = level + 1
end
end
p1 = Player.new
p1.broken_level_up
p1.level_up
puts p1.levelВывод:
level is a new local variable here, still nil
2Читателям не нужно self.: level и self.level вызывают один и тот же метод. В обычном стиле self. пишут только там, где это необходимо Ruby, — перед сеттером:
class Rect
attr_accessor :w, :h
def initialize(w, h)
@w = w
@h = h
end
def area
w * h
end
def double!
self.w = w * 2
self.h = self.h * 2
self
end
end
puts Rect.new(2, 3).double!.areaРезультат:
24Вызов сеттера из initialize с помощью self. позволяет новым объектам проходить ту же проверку, что и последующим изменениям, поэтому правило находится в одном месте:
class Product
attr_reader :price
def initialize(price)
self.price = price
end
def price=(value)
raise ArgumentError, "price must be positive" if value <= 0
@price = value
end
end
puts Product.new(5).price
begin
Product.new(0)
rescue ArgumentError => e
puts e.message
endРезультат:
5
price must be positiveТо, чем является self, зависит от того, где выполняется код. Внутри метода экземпляра это экземпляр; в теле класса, вне любого метода, это сам класс:
class Robot
puts "in the class body, self is #{self}"
def whoami
"in a method, self is a #{self.class}"
end
end
puts Robot.new.whoamiВывод:
in the class body, self is Robot
in a method, self is a RobotЗадание
ЛегкоУ класса Account есть пользовательский сеттер balance=, который вызывает ошибку ArgumentError с сообщением balance cannot be negative для значения меньше 0. Заверши initialize(owner, balance), deposit(amount) и withdraw(amount) так, чтобы каждое изменение баланса проходило через этот сеттер с использованием self., включая начальный баланс.
Предоставленный код считывает имя владельца и начальный баланс, затем обрабатывает команды +n (пополнение) или -n (снятие). После каждой команды он выводит Ada: 120 либо сообщение об ошибке и неизменённый баланс. При недопустимом начальном балансе выводится только сообщение об ошибке.
Твой код должен находиться в account.rb. В main.rb содержится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
require_relative 'account'
# Предоставленный код ввода/вывода: оставьте его как есть
input = []
while (line = gets)
input << line.chomp
end
begin
account = Account.new(input[0], input[1].to_i)
input.drop(2).each do |cmd|
begin
amount = cmd[1..].to_i
cmd.start_with?("+") ? account.deposit(amount) : account.withdraw(amount)
rescue ArgumentError => e
puts e.message
end
puts "#{account.owner}: #{account.balance}"
end
rescue ArgumentError => e
puts e.message
end
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПеременные экземпляраМетоды и selfto_s и inspectПовторение — читательский билет4Инкапсуляция
Приватные методыЗащищённые методыПриватные сеттерыЗащита состоянияПовторение — торговый автомат7Полиморфизм и утиная типизация
ПолиморфизмУтиная типизацияАбстрактные методыcase и классыПовторение — способы оплаты10Шаблоны проектирования, часть 2
Делегирование с помощью ForwardableШаблон декоратораШаблон строителяШаблон состояния2Аксессоры и self
Чтение и записьПользовательские сеттерыself в методахИдентичность и равенствоПовторение — список контактов5Наследование
ПодклассыПереопределение методовВызов superis_a? и предкиПовторение — расчёт зарплаты сотрудников8Специальные методы
Равенство и хешированиеМетоды операторовИндексация и добавлениеПользовательские коллекцииПовторение — дроби11Проект: Управление библиотекой
Книги и читателиВыдача книг3Методы и переменные классов
Методы классовПеременные экземпляра классаКонстантыФабричные методыПовторение — коды купонов6Модули и примеси
Модули и includeРасширение объектовМодуль ComparableМодуль EnumerableПовторение — спортивная лига9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор Ruby