我只想使用Null对象设计模式,但我发现我可以从NilClass继承。
我可以写一个方法“nil?”并返回false,但如果用户在下面编写代码
if null_object
puts "shouldn't be here"
end
澄清我尝试做的是:
record = DB.find(1)
# if it can not find record 1, the bellow code should not raise exception
record.one_attr
# and what's more
if record
puts "shouldn't be here"
end
# I don't want to override all NilClass
答案 0 :(得分:3)
可能适用于您的方法是覆盖方法#nil?在你的Null对象中。 这意味着在你的代码中测试null你必须使用obj.nil?而不只是检查obj存在。这可能是合理的,因为您可以区分nil和null。以下是一个例子:
class NullClass
def nil?
true
end
def null_behavior
puts "Hello from null land"
end
end
继承将起作用:
class NewClass < NullClass
end
像这样使用:
normal = Class.new
null = NewClass.new
x = [normal, null]
x.each do |obj|
if obj.nil?
puts "obj is nil"
obj.null_behavior
end
end
输出:
obj is nil
Hello from null land
记得使用#.nil?对于任何需要Null和Nil为false-ish的检查。
CustomNil = Class.new(NilClass)
class CustomNil
def self.new
###!!! This returns regular nil, not anything special.
end
end
[为简洁而删除的测试]
使用风险自负。我还没有研究过这可能会导致什么副作用,或者它是否会做你想要的。但它似乎确实有一些零行为
答案 1 :(得分:0)
我不认为Ruby实际上允许你从NilClass继承并基于它创建一个对象:
class CustomNilClass < NilClass
end
custom_nil_object = CustomNilClass.new
# => NoMethodError: undefined method `new' for CustomNilClass:Class
答案 2 :(得分:0)
我没有继承NilClass
,而是执行以下操作
class NullObject < BasicObject
include ::Singleton
def method_missing(method, *args, &block)
if nil.respond_to? method
nil.send method, *args, &block
else
self
end
end
end
这为您提供了猴子修补NilClass
的任何自定义方法(例如ActiveSupport&#39; s blank?
和nil?
)。您当然也可以添加自定义空对象行为,或者更改method_missing
以不同方式处理其他调用(这个返回NullObject以进行链接,但您可以返回nil
例如)。