Давайте определим экземпляр вашего класса SimpleMath
:
sm = SimpleMath.new #=> #<SimpleMath:0x000001020ca820>
Здесь следует отметить три вещи:
sm
- это переменная. В Ruby переменные представлены строчными буквами, которые могут быть разделены символом подчеркивания (например, my_var
).
- в то время как можно добавить
()
после new
, когда new
не имеет аргументов (так называемых «параметров»), это необязательно и обычно не делается.
- если ключевое слово
return
отсутствует, Ruby возвращает последнее вычисление, выполненное методом. Здесь вы обычно пишете последнюю строку просто как self
, и это будет возвращено. Увы, это не имеет значения, поскольку возврат self
с ключевым словом return
или без него — это не то, что вам нужно.
Попробуйте следующее в IRB:
sm.add(2) #=> #<SimpleMath:0x000001020ca820>
Вы, несомненно, ожидали, что это вернет 2+0 #=> 2
, но вместо этого оно вернуло self
, что, как вы можете видеть выше, на самом деле равно sm
(#<SimpleMath:0x000001020ca820>
).
Вы можете исправить это, просто удалив строку:
return self
от add
и subtract
:
class SimpleMath
def add(a,b=0)
a + b
end
def subtract(a,b=0)
a - b
end
end
Теперь
sm = SimpleMath.new
sm.add(2) #=> 2
Однако, если мы попытаемся связать еще один add
, у нас будет другая проблема:
sm.add(2).add(2,3) #=> NoMethodError: undefined method `add' for 2:Fixnum
Это сообщение очень ясное: класс Fixnum
, экземпляром которого является 2
, не имеет метода экземпляра с именем add
. Это потому, что вы определили его для класса SimpleMath
, а не для Fixnum
.
Когда Ruby выполняет sm.add(2).add(3,4)
, он сначала вычисляет sm.add(2) #=> 2
, что сокращает выражение до 2.add(3,4)
. Затем он пытается отправить метод add
(с двумя его параметрами) в 2
, но обнаруживает, что класс 2.class #=> Fixnum
не имеет метода экземпляра add
; отсюда и исключение.
Мы можем исправить эту ошибку, определив вместо этого эти методы для класса Fixnum
:
class Fixnum
def add(a,b=0)
a + b
end
def subtract(a,b=0)
a - b
end
end
Вы можете подтвердить, что эти методы были добавлены в класс Fixnum
, выполнив:
Fixnum.instance_methods.sort
Теперь другая проблема:
sm = Fixnum.new #=> NoMethodError: undefined method `new' for Fixnum:Class
О боже, в классе Fixnum
нет метода new
! Это потому, что экземпляры Fixnum
являются целыми числами, которые нельзя создать. Вы можете легко подтвердить, что целые числа являются экземплярами Fixnum
:
72.class #=> Fixnum
-3.class #=> Fixnum
Таким образом, мы можем вызвать метод add
, отправив его в любой экземпляр Fixnum
:
72.add(2) #=> 2
-3.add(2) #=> 2
Теперь попробуем связать add
операций:
72.add(2).add(3,4) #=> 7
72.add(2000000).add(3,4) #=> 7
Не исключение, но и не цепочка. Чтобы исправить это, нужно еще раз изменить методы:
class Fixnum
def add(b=0)
puts "in add, self = #{self}, b = #{b}"
self + b
end
def subtract(b=0)
puts "in subtract, self = #{self}, b = #{b}"
self - b
end
end
Я добавил оператор puts
в каждый метод на случай, если потребуется дополнительная отладка. Мы удалим их, когда код заработает правильно. Давайте проверим:
2.add(3) #=> 5
in add, self = 2, b = 3
5.add #=> 5
in add, self = 5, b = 0
5.add(7) #=> 12
in add, self = 5, b = 7
2.add(3).add.add(7) #=> 12
in add, self = 2, b = 3
in add, self = 5, b = 0
in add, self = 5, b = 7
2.subtract(5) #=> -3
in subtract, self = 2, b = 5
-3.subtract #=> -3
in subtract, self = -3, b = 0
2.subtract(5).subtract #=> -3
in subtract, self = 2, b = 5
in subtract, self = -3, b = 0
2.add(3).subtract(5).add(7) #=> 7
in add, self = 2, b = 3
in subtract, self = 5, b = 5
in add, self = 0, b = 7
Успех! Возьми?
person
Cary Swoveland
schedule
09.07.2014
add(2)
не имеет смысла, если вы не сохраняете результат в экземпляре. - person Dave Newton   schedule 09.07.2014