3

編集 | または、同じオブジェクトの件名に関する別の質問。次のすべてを機能させる独自のクラス定義を作成できますか?

o = WeirdObject.new
puts "Object o evaluates as true in boolean expressions" if o # Line never output
puts "Object o is nil?" if o.nil? # Line is output

nil?それは単なる方法なので、簡単にできます。しかし、ブール式(最も基本的な式「o」のみを含む)で真ではない値として評価する方法がわかりません。

元の質問は次のとおりです...

Ruby (1.9.2) でどれだけ楽しめるかという好奇心から...

ユーザーがログインしていないときは、with unless @useror until@user.nil?などで検出できるようにしたいのですが、同時に、このオブジェクトのメソッドを呼び出してUser同じものを返してもらいたいです(ala Objective-C)。ほとんどの場合、これによりボイラープレートコードNilClassが不要になるため、ブール式のように動作します。if @usernil

NilClassメソッドがないため、サブクラス化できないことがわかりました#new。メソッドをインスタンスに直接追加できますが、これはシングルトンであるため、この動作を確認したい場所がログインしていないユーザーだけである場合、問題が発生します。

出来ますか?

つまり、次のようなものです。

class CallableNil < NilClass
  def method_missing(meth, *args, &block)
    self
  end
end

user = CallableNil.new # or .singleton, or something

puts "Got here" unless user # Outputs
puts "And here" unless user.nil? # also outputs

puts user.username # no-op, returns nil

これは基本的に Objective-C が nil を処理する方法であり、状況によっては便利です。

NilClass をサブクラス化できず、ブール式で false になるメソッドを実装できなかったと思いますか?

編集 | ははは、トップレベルを再定義すると、本当にRubyがかなり壊れてしまいますNilClass...メソッド呼び出しにまったく応答しなくなります。

>> class NilClass
>>   def method_missing(meth, *args, &block)
>>     self
>>   end
>> end
>> 
?> nil.foo
>> 
?> 
?> puts "here"
>> quit
>> # WTF? Close dammit!
4

4 に答える 4

3

nil主な要件が、例外を発生させずに (または定義されていることを確認する必要なく) 値に対してメソッドを呼び出せるようにすることである場合は、次のようにActiveSupport追加Object#tryします。

instance = Class.method_that_returns_nil

unless instance
  puts "Yes, we have no instance."
end

instance.try(:arbitrary_method)             # => nil
instance.try(:arbitrary_method, "argument") # => nil

これまで見てきたように、いじくり回すとNilClass興味深い副作用がいくつかあります。

于 2011-05-08T02:48:21.980 に答える
2

別の潜在的な解決策 (スレッドセーフではない):

def null!
  @@null_line = caller.first
end

class NilClass
  def method_missing(name, *args, &block)
    if caller.first == @@null_line
      nil
    else
      super
    end
  end
end


null!; nil.a.b.c.d.e # returns nil
nil.a # throws an error
于 2012-11-21T08:13:03.520 に答える
2

nil通常、この方法でオブジェクトを変更することはお勧めしません-- fail-fastegonilまたはandand gemを使用することをお勧めします。このトピックに関するその他の読み物/リンクについては [そしてお楽しみに ;)]、このブログ投稿をチェックしてください。

于 2011-05-08T02:41:45.943 に答える