与超级混淆

时间:2010-11-15 16:18:55

标签: ruby-on-rails ruby super

覆盖to_xml。

这些代码之间有什么区别。有人可以用适当的例子来解释它吗?

1

def to_xml(options = {})
  options.merge!(:methods  => [ :murm_case_name, :murm_type_name ])
  super
end

2

def to_xml(options = {})
  super
  options.merge!(:methods  => [ :murm_case_name, :murm_type_name ])
end

2 个答案:

答案 0 :(得分:4)

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使用变量options来调用super方法,该变量引用值Fixnum的{​​{1}},而不是最初的对象由42提及。

使用options,您将修改传递给您的哈希对象,这意味着变量options.merge!引用的对象现在已被修改,如{ {1}}行。

(注意:我在SecondChild中将original_child_options更改为42,而不是调用Original child options after method called: {:methods=>[:murm_case_name, :murm_type_name]},因为我想表明它不仅仅是对对象产生副作用的情况)

答案 1 :(得分:2)

首先返回超级调用的结果。所以就像你永远不会在你的情况下做点什么。

在您更改之前第二次调用super,并在之后更改选项。

我想你真的想要:

def to_xml(options = {})
  super(options.merge!(:methods  => [ :murm_case_name, :murm_type_name ]))
end