重新定义Ruby方法的怪异行为
为什么程序的输出是:重新定义Ruby方法的怪异行为,ruby,Ruby,为什么程序的输出是: require 'set' class Set alias :old_add :add def add(arg) arg = 5 old_add arg end end s = Set.new ([1,2]) s.add(3) puts s.inspect 存在 # 相对于 #<Set: {1,2,5}> # 方法add被重新定义为与参数5一起运行,查看以下内容的源: 似乎Set.new在内部调用方法#add。在OP的示
require 'set'
class Set
alias :old_add :add
def add(arg)
arg = 5
old_add arg
end
end
s = Set.new ([1,2])
s.add(3)
puts s.inspect
存在
#
相对于
#<Set: {1,2,5}>
#
方法add
被重新定义为与参数5
一起运行,查看以下内容的源:
似乎Set.new
在内部调用方法#add
。在OP的示例中,块
为nil
,因此称为:
# File set.rb, line 351
def merge(enum)
if enum.instance_of?(self.class)
@hash.update(enum.instance_variable_get(:@hash))
else
# in your case this else part will be executed.
do_with_enum(enum) { |o| add(o) }
end
self
end
因此,为enum
的每个元素调用add
([1,2]
)。这里,您覆盖了原始的#add
方法,在该方法中,您使用参数5
调用旧的#add
方法
Set实现了一个无重复项的无序值的集合。因此,即使您添加了两次5
,也只能得到一个5
。这就是为什么您没有得到
,而是
。如下所示,当您调用Set.new
时,将创建对象#
,正如我上面解释的那样:
require 'set'
class Set
alias :old_add :add
def add(arg)
arg = 5
old_add arg
end
end
s = Set.new ([1,2])
s # => #<Set: {5}>
require'set'
类集
别名:old_add:add
def添加(arg)
arg=5
old_add arg
结束
结束
s=Set.new([1,2])
s#=>#
当调用
s.add(3)
时,调用了重写的add
方法,它再次将5
传递给旧的add
方法。如前所述,Set
不包含重复的值,因此对象仍将与先前的#
相同。当您使用给定成员实例化一个新集合时,将使用add
方法添加成员。这可以通过在创建集合后调查集合来显示:
Set.new([1,2])
# => #<Set: {5}>
Set.new([1,2])
# => #
因此,当您执行s.add(3)
时,基本上是再次添加5
,它已经添加到集合中两次,因此该方法实际上不会更改集合
require 'set'
class Set
alias :old_add :add
def add(arg)
arg = 5
old_add arg
end
end
s = Set.new ([1,2])
s # => #<Set: {5}>
Set.new([1,2])
# => #<Set: {5}>