我很好奇是否有更短的方法来检查是否在对象上定义了方法,如果是,则检查它是否为零。我试过了:
if !obj.respond_to?(:meth) || obj.meth.nil?
但它看起来很长很难看。
答案 0 :(得分:3)
快速又脏又简洁:
unless (obj.meth rescue nil)
...
end
如果向meth
发送obj
失败(例如因为方法丢失),则表达式采用值nil
。
当然,这会隐藏meth
中的所有错误。
答案 1 :(得分:3)
正如@Sergio建议的那样,try
from ActiveSupport正是您想要的。使用try
,您的代码将如下所示:
if obj.try(:meth).nil?
# obj either lacks :meth or has :meth that returns nil
end
我认为非常简洁易读。
如果您没有使用ActiveSupport,您可以自己快速重新实现简单版try
:
class Object
def try(method, *args)
public_send(method, *args) if respond_to?(method)
end
end
答案 2 :(得分:2)
如果您使用的是rails,则可以使用.try
[1] pry(main)> h = {}
=> {}
[2] pry(main)> h.try(:foo)
=> nil
答案 3 :(得分:2)
部分是为了让它读得很好,我会这样做:
def has_method?(obj, method)
obj.methods.include?(method)
end
has_method?(2, :+) #=> true
has_method?('cat', :upcase) #=> true
has_method?('cat', :group_by) #=> false
has_method?(Array, :new) #=> true
所以它会是:
!has_method?(obj, :meth) || obj.meth.nil?
或只是:
!obj.methods.include?(:meth) || obj.meth.nil?
或:
!(obj.methods.include?(:meth) && obj.meth != nil)
答案 4 :(得分:1)
使用defined?
关键字。
irb(main):066:0> obj = "test" # in this case obj is a string
=> "test"
irb(main):067:0> defined? obj.split
=> "method"
irb(main):068:0> defined? obj.not_a_func
=> nil
定义?表达式测试表达式是否引用任何可识别的内容(文字对象,已初始化的局部变量, 方法名称从当前范围可见 等)。 如果无法解析表达式,则返回值为nil 。