Как наследовать от NilClass или как смоделировать подобную функцию - PullRequest
4 голосов
/ 09 марта 2011

Я просто хочу использовать шаблон проектирования пустых объектов, но обнаружил, что могу наследовать от NilClass.

Я могу написать метод "ноль?" и вернуть 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 ]

3 голосов
/ 10 марта 2011

Подход, который может работать для вас, состоит в том, чтобы переопределить метод #nil?в вашем нулевом объекте.Это означает, что в вашем коде для проверки на null вы должны использовать obj.nil?а не просто проверить наличие объекта.Это, вероятно, разумно, так как вы можете различить ноль и ноль.Ниже приведен пример:

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

[тесты удалены для краткости]

Использоватьна свой страх и риск.Я не исследовал, какие побочные эффекты это может вызвать или будет ли это делать то, что вы хотите.Но, похоже, у него есть ноль как поведение

0 голосов
/ 16 апреля 2015

Вместо того, чтобы наследовать от 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? и nil?).,Вы также можете, конечно, добавить пользовательское поведение нулевого объекта или изменить method_missing, чтобы по-другому обрабатывать другие вызовы (этот возвращает NullObject для объединения в цепочку, но вы можете, например, вернуть nil).

0 голосов
/ 10 марта 2011

Я не думаю, что Ruby на самом деле позволяет вам наследовать от NilClass и создавать на его основе объект:

class CustomNilClass < NilClass
end

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