Ruby 如何从类继承或如何模拟类似函数

Ruby 如何从类继承或如何模拟类似函数,ruby,truthiness,Ruby,Truthiness,我只想使用空对象设计模式,但我发现我可以从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 wha

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

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

class CustomNilClass < NilClass
end

custom_nil_object = CustomNilClass.new
# => NoMethodError: undefined method `new' for CustomNilClass:Class
class CustomNilClassNoMethodError:CustomNilClass:Class的未定义方法“new”

一种可能对您有效的方法是超越该方法#零?在空对象中。 这意味着在测试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
输出:

obj is nil
Hello from null land
记得用#.nil吗?对于要求Null和Nil为false的任何检查

这条线下面是我错误的初始答案 [为简洁起见删除测试]


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

而不是继承自
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
class NullObject

这将为您提供任何已被猴子补丁到
NilClass
上的自定义方法(例如ActiveSupport的
blank?
nil?
)。当然,您也可以添加自定义的空对象行为,或者更改
method\u missing
以不同方式处理其他调用(此调用返回用于链接的空对象,但您可以返回
nil

你能解释一下你想做什么吗?空对象重构的全部要点不是使用
nil
,那么为什么要从
NilClass
继承呢?只是想澄清一下:如果
Null\u对象
是自定义空对象类的对象,那么你希望
如果Null\u对象
意味着
“不应该在这里”
不会被打印出来?你是说“我可以从NilClass继承”还是“我不能从NilClass继承”?谢谢,你认为这有什么风险?我编辑了我的回答来回答你的问题,并说明我最初的回答是错的。那么你为什么说“但我发现我可以从NilClass继承”?
CustomNil = Class.new(NilClass) 

class CustomNil
  def self.new
    ###!!! This returns regular nil, not anything special.
  end
end
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