不带参数调用超级

Ste*_*fan 11 ruby

根据模块和类文档,调用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')
Run Code Online (Sandbox Code Playgroud)

输出:

MySubclass#foo("inital value")
MyClass#foo("inital value")
MyClass#foo("new value")       # <- not the argument given to MySubclass#foo
Run Code Online (Sandbox Code Playgroud)

这是预期的吗?

更新

似乎是位置和关键字参数的预期行为,但它不适用于块参数:

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' }
Run Code Online (Sandbox Code Playgroud)

输出:

MySubclass#foo { "initial value" }
MyClass#foo { "initial value" }
MyClass#foo { "initial value" }
Run Code Online (Sandbox Code Playgroud)

Aru*_*hit 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
Run Code Online (Sandbox Code Playgroud)

现在,看看测试用例: -

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

以上示例完全匹配关键字文档.

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

相同的参数意味着它说的是参数变量当前值.test_super.rb文件包含我们可以用superRuby 做的各种各样的东西.

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

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"
Run Code Online (Sandbox Code Playgroud)

但是,不知道下面给出的原因是"c"什么?这实际上是OP的更新问题:

c = Class.new do
  def foo(&block)
    block.call
  end
end

d = Class.new(c) do
  def foo(&block)
     block = -> { "b" }
    super
  end
end

d.new.foo{"c"} # => "c"
Run Code Online (Sandbox Code Playgroud)

  • 如果您不想要这种行为,只需调用`super()`即可在不带参数的情况下调用. (2认同)