不带参数调用超级

时间:2015-01-16 09:55:32

标签: ruby

根据documentation for modules and classes,调用super(不带参数或括号)使用相同的参数调用父方法:

  

在没有任何参数的情况下使用时super使用给予子类方法的参数。

为"参数变量"分配一个新值。似乎改变了这种行为:

class MyClass
  def foo(arg)
    puts "MyClass#foo(#{arg.inspect})"
  end
end

class MySubclass < MyClass
  def foo(arg)
    puts "MySubclass#foo(#{arg.inspect})"
    super
    arg = 'new value'
    super
  end
end

MySubclass.new.foo('inital value')

输出:

MySubclass#foo("inital value")
MyClass#foo("inital value")
MyClass#foo("new value")       # <- not the argument given to MySubclass#foo

这是预期的吗?

更新

seems to be位置和关键字参数的预期行为,但它不适用于块参数:

class MyClass
  def foo(&block)
    puts "MyClass#foo { #{block.call.inspect} }"
  end
end

class MySubclass < MyClass
  def foo(&block)
    puts "MySubclass#foo { #{block.call.inspect} }"
    super
    block = Proc.new { 'new value' }
    super
  end
end

MySubclass.new.foo { 'initial value' }

输出:

MySubclass#foo { "initial value" }
MyClass#foo { "initial value" }
MyClass#foo { "initial value" }

3 个答案:

答案 0 :(得分:9)

让我们从Ruby核心中拿一个例子:

Keyword2

class Base
  def single(a) a end
  def double(a, b) [a,b] end
  def array(*a) a end
  def optional(a = 0) a end
  def keyword(**a) a end
end

class Keyword2 < Base
  def keyword(foo: "keyword2")
    foo = "changed1"
    x = super
    foo = "changed2"
    y = super
    [x, y]
  end
end

现在,请参阅test case: -

def test_keyword2
  assert_equal([{foo: "changed1"}, {foo: "changed2"}], Keyword2.new.keyword)
end

上面的例子恰好与keyword documentation匹配。

  

在没有参数且没有空参数列表的情况下调用,super调用具有相同参数的相应方法,并使用与调用当前方法相同的代码块 。使用参数列表或参数调用,它使用指定的参数调用适当的方法(包括无,在空括号表示空参数列表的情况下)。

相同的参数意味着它说参数变量的当前值test_super.rb文件包含我们可以使用{{1}进行的各种事情。在Ruby中。

不,它也适用于块(取自core):

super

但是,不知道为什么下面给出了a = Class.new do def foo yield end end b = Class.new(a) do def foo super{ "b" } end end b.new.foo{"c"} # => "b" ?这实际上是OP的更新问题:

"c"

答案 1 :(得分:4)

这似乎是预期的行为,无论如何都基于RubySpec

module RestArgsWithSuper
  class A
    def a(*args)
      args
    end
  end

  class B < A
    def a(*args)
      args << "foo"

      super
    end
  end
end

language/fixtures/super.rb)。

然后期望修改参数:

it "passes along modified rest args when they weren't originally empty" do
  Super::RestArgsWithSuper::B.new.a("bar").should == ["bar", "foo"]
end

language/super_spec.rb

答案 2 :(得分:0)

这是预期的行为。从技术上讲,arg是相同的参数,只是指向另一个值。

这个答案可能会更好地解释:https://stackoverflow.com/a/1872159/163640