tl; dr: super
ведет себя неожиданным образом, и переменные имеют значение, а не только объекты.
Когда вызывается super
, он не вызывается с объектом, который был
Вызывается с переменной, которая называется options
во время вызова.Например, со следующим кодом:
class Parent
def to_xml(options)
puts "#{self.class.inspect} Options: #{options.inspect}"
end
end
class OriginalChild < Parent
def to_xml(options)
options.merge!(:methods => [ :murm_case_name, :murm_type_name ])
super
end
end
class SecondChild < Parent
def to_xml(options)
options = 42
super
end
end
begin
parent_options, original_child_options, second_child_options = [{}, {}, {}]
Parent.new.to_xml(parent_options)
puts "Parent options after method called: #{parent_options.inspect}"
puts
OriginalChild.new.to_xml(original_child_options)
puts "Original child options after method called: #{original_child_options.inspect}"
puts
second_child_options = {}
SecondChild.new.to_xml(second_child_options)
puts "Second child options after method called: #{second_child_options.inspect}"
puts
end
, который производит вывод
Parent Options: {}
Parent options after method called: {}
OriginalChild Options: {:methods=>[:murm_case_name, :murm_type_name]}
Original child options after method called: {:methods=>[:murm_case_name, :murm_type_name]}
SecondChild Options: 42
Second child options after method called: {}
Вы можете видеть, что с SecondChild
метод super вызывается с переменной options
, котораяотносится к Fixnum
значения 42
, а не к объекту, на который изначально ссылался options
.
При использовании options.merge!
вы измените объект хеша, который был передан вамЭто означает, что объект, на который ссылается переменная original_child_options
, теперь изменен, как это видно в строке Original child options after method called: {:methods=>[:murm_case_name, :murm_type_name]}
.
(Примечание: я изменил options
на 42 в SecondChild, а незвоните Hash#merge
, потому что я хотел показать, что это был не просто случай побочных эффектов на объект)