Проблема не имеет ничего общего с RSpec. Проблема здесь:
@timer.seconds = 0
Это ничего не значит для класса, который вы определили. Вы не сказали перед классом, что означает seconds =
, так что вы получите сообщение об ошибке undefined method `seconds='
.
В своем классе, у вас есть метод, названный seconds
:
def seconds
0
end
... но все это делает метод возвращен 0
при вызове @timer.seconds
. Он ничего не делает.
Если вы хотите, чтобы иметь возможность звонить @timer.seconds = x
, вам необходимо определить способ сделать это в своем классе. Один из способов заключается в определении seconds=
метод:
class Timer
def seconds=(num)
@seconds = num
end
# ...
end
С помощью этого метода, когда вы звоните @timer.seconds = 3
, вы на самом деле вызов метода seconds=
с аргументом 3
и метод seconds=
присваивает 3
к экземпляру переменной @seconds
(так как вам нужно где-то сохранить значение внутри экземпляра вашего класса).
Это настолько распространено в Рубине, что есть ярлык для этого, метод класса attr_writer
(«атр» является аббревиатурой «атрибут»), который вы используете, как это:
class Timer
attr_writer :seconds
# ...
end
Все это делает создайте для нас метод seconds=
, как и код выше.
Но теперь, когда мы сохранили значение в переменной экземпляра @seconds
, как нам его вернуть? Если мы хотим, чтобы @timer.seconds
возвращал 3
(значение, которое мы назвали seconds=
), нам нужен метод seconds
, возвращающий значение переменной экземпляра @seconds
.Это просто:
class Timer
attr_writer :seconds # (from above)
def seconds
@seconds
end
# ...
end
Теперь мы можем хранить значение с seconds=
и получить его обратно с seconds
:
@timer = Timer.new
@timer.seconds = 60
puts @timer.seconds
# => 60
Но, как вы, возможно, уже догадались, у нас есть ярлык для этого, слишком attr_reader
метод класса:
class Timer
attr_writer :seconds
attr_reader :seconds
# ...
end
Но у нас есть еще один ярлык, если мы имеем attr_reader
и attr_writer
с тем же именем, мы можем сделать как метод класса attr_accessor
:
class Timer
attr_accessor :seconds
# ...
end
@timer = Timer.new
@timer.seconds = 5
puts @timer.seconds
# => 5
Это чрезвычайно полезное и понятное объяснение. Был способен заставить программу работать. спасибо – Andrew