如何从NilClass继承或如何模拟类似的功能

时间:2011-03-09 08:46:31

标签: ruby truthiness

我只想使用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

3 个答案:

答案 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例如)。