4

我只想使用空对象设计模式,但我发现我可以从 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
4

3 回答 3

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 为假的检查。

在这条线下面是我错误的初始答案

CustomNil = Class.new(NilClass) 

class CustomNil
  def self.new
    ###!!! This returns regular nil, not anything special.
  end
end

[为简洁起见删除了测试]

使用风险自负。我还没有研究这可能会导致什么副作用,或者它是否会达到你想要的效果。但它似乎确实有一些类似 nil 的行为

于 2011-03-09T23:09:51.580 回答
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(例如 ActiveSupportblank?nil?)。当然,您也可以添加自定义空对象行为,或更改method_missing以不同方式处理其他调用(此调用返回 NullObject 以进行链接,但您可以返回nil例如)。

于 2015-04-16T20:25:23.120 回答
0

我不认为 Ruby 实际上允许您从 NilClass 继承并基于它创建对象:

class CustomNilClass < NilClass
end

custom_nil_object = CustomNilClass.new
# => NoMethodError: undefined method `new' for CustomNilClass:Class
于 2011-03-09T22:20:41.873 回答