5

オブジェクトが不変 (数値、nil) かそうでない (配列、ハッシュ、オブジェクト) かをテストする簡単な方法はありますか? つまり、他のコードからの副作用によって変更される可能性はありますか?

動機: バージョン管理された値ストアを作成したいのですが、一部のデータは配列です。一部の配列にはカスタム オブジェクトが格納されますが、「in」プロパティを格納して検索することで関係を逆転させることができます。しかし、シンボルの配列や他の配列なども保存できるようにしたいと思います.

4

4 に答える 4

6

私は非効率的な方法を見つけました:

class Object
  def primitive?
    begin
      self.dup
      false
    rescue TypeError
      true
    end
  end
end
于 2009-01-18T16:35:56.473 に答える
4

There are no primitive objects in Ruby. This can therefore not be detected in a straightforward manner.

Can't you simply use Marshal or YAML for your versioned store? Then you'll get loading and saving of all object types for free. Why reinvent the wheel?

I don't know what you want to achieve exactly, but looking at the source of YAML may be interesting to see how they handle this problem. The Ruby YAML encoding implementation simply implements the to_yaml method for all relevant classes. See yaml/rubytypes.rb.

于 2009-01-18T16:53:57.013 に答える
2

可変性の概念は、他の言語と同じようにRubyには実際には当てはまりません。唯一の不変オブジェクトはフリーズされたオブジェクトです。メソッドとインスタンス変数をFixnumsに追加することもできます。例えば:

class Fixnum
  attr_accessor :name
end
1.name = "one"
2.name = "two"

明らかに、ほとんどの場合、人々はFixnumに属性を追加するのに十分な病的状態にはなりませんが、要点は、凍結されていないオブジェクトが本当に不変であるということではありません。

不変であると想定したいクラスの標準的なリストを思い付くことができれば、それらすべてimmutable?()にtrueを返すメソッド(およびObjectはfalseを返すバージョン)を与えることができます。しかし、wvanbergenが言ったように、オブジェクトのコピーが変更されないようにするための最良の方法は、Marshalでオブジェクトをディープコピーすることです。

于 2009-01-18T20:53:29.793 に答える
1

もう1つの違い:ネイティブに不変のオブジェクトはフリーズできませんが、フリーズするとfalseが返されますか?

5.freeze.frozen? == false

Freezeは(dupとは異なり)例外を発生させませんが、(永続的に!)可変オブジェクトを変更します。

(少なくとも現在の状態では)フリーズしたオブジェクトで動作するようにアプリを調整できることがわかりました。それらを直接変更しようとすると、rubyで例外が発生します。ただし、フリーズはオブジェクトの最初のレベルにのみ影響し、オブジェクトに格納されている配列などは引き続き変更できます。

これは1.8-5.frozenにのみ適用されますか?ruby1.9ではtrueを返します(irb1.9では返しません)

于 2009-01-18T20:44:48.843 に答える