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

发布于 2024-10-20 18:11:59 字数 419 浏览 3 评论 0原文

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

I just want to use Null Object Design Pattern, but I found I can inherit from NilClass.

I can write a method "nil?" and return false but what if user write code below

if null_object 
  puts "shouldn't be here"
end

For clarify what I try to do is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

尐籹人 2024-10-27 18:11:59

可能对您有用的一种方法是覆盖方法#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 的检查。

在这一行下面是我错误的初始答案

CustomNil = Class.new(NilClass) 

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

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

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

An approach that may work for you is to overide the method #nil? in your Null object.
This means that in your code to test for null you have to use obj.nil? and not just check for obj existence. This is probably reasonable, since you can distinguish between nil and null. Below is an example:

class NullClass
  def nil?
    true
  end

  def null_behavior
    puts "Hello from null land"
  end
end

Inheritance will work:

class NewClass < NullClass
end

Use like so:

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

Output:

obj is nil
Hello from null land

Just remember to use #.nil? for any checks that require Null and Nil to be false-ish.

Below this line was my WRONG initial answer

CustomNil = Class.new(NilClass) 

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

[tests deleted for brevity]

Use at your own risk. I haven't researched what side effects this may cause or whether it will do what you want. But it seems it does have some nil like behavior

月下凄凉 2024-10-27 18:11:59

我没有从 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 的 blank?无?)。当然,您还可以添加自定义空对象行为,或更改 method_missing 以不同方式处理其他调用(此方法返回 NullObject 进行链接,但您可以返回 nil 例如) 。

Instead of inheriting from NilClass I do the following

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

This gives you any custom method that have been monkey patched onto NilClass (such as ActiveSupport's blank? and nil?). You can also of course add custom null object behaviors, or change method_missing to handle other calls differently (this one returns the NullObject for chaining, but you could return nil for example).

岁吢 2024-10-27 18:11:59

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

class CustomNilClass < NilClass
end

custom_nil_object = CustomNilClass.new
# => NoMethodError: undefined method `new' for CustomNilClass:Class

I don't think Ruby actually allows you to inherit from NilClass and create an object based on it:

class CustomNilClass < NilClass
end

custom_nil_object = CustomNilClass.new
# => NoMethodError: undefined method `new' for CustomNilClass:Class
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文