根据模块和类的文档,调用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)
让我们从Ruby核心中举一个例子:
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)