在控制台中:
class Logger
end
l = Logger.new
引发错误:ArgumentError: wrong number of arguments (0 for 1)
from /home/zzz/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/logger.rb:268:in 'initialize'
为什么在/home/zzz/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/logger.rb
中使用记录器?
答案 0 :(得分:3)
我会尽力回答你的第二个问题。那么,为什么Ruby使用其他Logger
类而不是你自己定义的那个?
Ruby的一个基本功能是重新打开类。假设您已经在应用中定义并加载了一些类:
class A
def foo
puts 'foo'
end
end
A.new.foo
#=> foo
如果之后Ruby解释器遇到类似的事情:
class A
def bar
puts 'bar'
end
end
它不会重新定义类A
,而只是将此定义附加到前一个定义。在已定义的结果中,类A
获取新的实例方法bar
:
A.new.foo # still works
#=> foo
A.new.bar # new method
#=> bar
由于Ruby处理方法调用的方式,在类A
的第二个定义(实际上,重新打开)之前初始化的类A
的所有实例也得到这个新方法bar
。因此,每次重新打开一个类时,都会向类本身以及此类的所有先前初始化的实例添加新功能。
重新打开类也允许重写现有类的方法:
class A
def foo
puts 'new foo'
end
end
A.new.foo
#=> new_foo
考虑到这一特性以及Rails已经为您加载了标准Logger
类这一事实,您的定义只会重新打开该类,但甚至不会更改任何内容。
答案 1 :(得分:2)
那个类已经加载了,大概是因为rails正在使用它:你没有重新定义类,你只是重新打开它。
您可以删除现有的课程
Object.send(:remove_const, :Logger)
在这种情况下,以前称为Logger
的类仍然存在,它只是不再与常量Logger
绑定,所以当你这样做时
class Logger
end
你将创建一个不重新打开旧类的新类。当然,您最终可能会破坏假定存在旧Logger类的代码。
如果你在测试中这样做,你可能会对rspec 2.11中的新constant stubbing感兴趣