为什么NoMethodError
没有区分Ruby中的nil
?
在nil上调用方法是一个非常常见的错误,通常是由提供给程序的错误数据引起的。任何其他类的NoMethodError
通常意味着代码本身出错(例如,为什么你在reconnect
上调用Document
?代码中可能存在错误。
如果我将以下代码添加到项目中会产生哪些问题?
NilReferenceError = Class.new(NoMethodError)
class NilClass
def method_missing(symbol, *args)
raise NilReferenceError, "undefined method `#{symbol}' for nil:NilClass", caller
end
end
我想这样做是因为当我对异常进行分类时,NilReferenceError
可能是由错误的数据引起的,根本原因很可能是在另一个位置(例如,输入的验证)。相比之下,NoMethodError
可能是一个完全根据异常行编写的编程错误(更容易修复,并且很可能100%发生)。
将类似代码添加到我的项目中有什么负面影响?
答案 0 :(得分:1)
我认为这只是其他编程语言的习惯。在ruby中,nil是一个第一类对象,如整数,散列或您自己的类对象。
一旦看到"NoMethodError: undefined method xxx for nil:NilClass"
错误一次或两次,就会习惯它。
答案 1 :(得分:0)
你的意思是,在做b=nil; b.say_hello;
这样的事情时,ruby会给你"未定义的方法`say_hello'对于nil:NilClass( NoMethodError )"而不是像(在你的说法中)那样的东西"未定义的方法`say_hello' for nil:NilClass( NilReferenceError )"?
Ruby没有错,因为nil
是一个像其他对象一样的对象。它有to_s
之类的方法,所以ruby不能通过提出异常来禁止任何调用"因为它是零,你不能做任何事情。我会给你一个NilReferenceError"。
如果你知道你正在做的事情可能会阻止ruby的默认行为,你肯定可以像上面的代码一样。
答案 2 :(得分:0)
monkeypatching nil
显示更具描述性的错误消息没有错,但它无法解决问题的根本原因,即编码实践允许和传播nil值。
考虑以下非常人为的例子:
def do_something(input)
object = fetch_something_with(input[element])
do_something_with(object)
end
这可能会爆发几种方式:
input
哈希不包含element
,并将nil
传递给fetch_something_with
fetch_something_with
返回nil(按设计或失败时),将其传递到do_something_with
另一种方法可能是:
def do_something(input)
object = fetch_something_with(validated_input)
object && return do_something_with(object)
end
def validated_input(input)
input.fetch(element) # fetch raises an exception if the value is not present
end
稍微多一些代码,但它让我们高枕无忧,这段代码不会默默地将nil
传递给线路,以便稍后失败。
当然,在每种方法中成为这种偏执都没有意义,但是在方法或对象层面上,在代码中有一个深思熟虑的边界是一种好习惯。 nil
经常出现问题表明这些边界需要加强。