4

Null Object Design Patternを使用したいのですが、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がfalseっぽいことを要求するチェックの場合。

この線の下に私の間違った最初の答えがありました

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

Rubyでは実際にNilClassから継承し、それに基づいてオブジェクトを作成することはできないと思います。

class CustomNilClass < NilClass
end

custom_nil_object = CustomNilClass.new
# => NoMethodError: undefined method `new' for CustomNilClass:Class
于 2011-03-09T22:20:41.873 に答える
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?)が提供されます。もちろん、カスタムnullオブジェクトの動作を追加したり、method_missing他の呼び出しを別の方法で処理するように変更したりすることもできます(これは、連鎖のためにNullObjectを返しますが、たとえば、返すことができますnil)。

于 2015-04-16T20:25:23.120 に答える