0

Marshal.loadハッシュのサブクラスのMarshal.dumpedインスタンスを管理できません:

class MarshalDumpableHash < Hash

  def initialize(constructor = {})
    if constructor.is_a?(Hash)
      super()
      update(constructor)
    else
      super(constructor)
    end
  end

  def marshal_dump
    p self
    self
  end

  def marshal_load(hash)
    p hash
    update(hash)
  end

end


h = { asd: 'ciao' }

p MarshalDumpableHash.new(h) #=> {:asd=>"ciao"}
p Marshal.dump(MarshalDumpableHash.new(h)) #=> "\x04\bU:\x18MarshalDumpableHash@\x00"

p Marshal.load(Marshal.dump(MarshalDumpableHash.new(h))) #=> {} WHY?

メソッドの内部が印刷されるのに対し、メソッドのp self内部が印刷されるのは奇妙に聞こえますmarshal_dump{:asd=>"ciao"}marshal_load{}

4

1 に答える 1

2

組み込みのダンプとロードがそれを行うため、メソッドmarshal_dumpreturningはandselfを使用するユースケースではありません。したがって、マーシャリングするだけの場合は、カスタマイズされたまたはを記述する必要はありません。marshal_dumpmarshal_loadselfmarshal_dumpmarshal_load

class Subclassed < Hash
end

s = Subclassed.new
s[:foo] = :bar
Marshal.load(Marshal.dump(s)).class #=> Subclassed

これらのメソッドは、ダンプされたオブジェクトをロードするときにリロードしたくないオブジェクトに関する余剰情報がある場合のユースケース用です。これはスペースを節約するためです。例えば:

class Subclassed < Hash

  attr_reader :surplus_info

  def initialize(surplus_info)
    @surplus_info = surplus_info
  end

  def marshal_dump
    Hash.new.merge(self)
  end

  def marshal_load other
    update(other)
  end
end

marshal_dumpおよびがないmarshal_load場合、結果のマーシャリングされた文字列は次のようになります。

"\004\bIC:\017Subclassed{\006:\bfoo:\bbar\006:\022@surplus_info\"\bfoo"

余剰情報があります。マーシャルのロードとダンプを使用すると、マーシャリングされた文字列を減らすことができます。

"\004\bIU:\017Subclassed{\006:\bfoo:\bbar\000" 

これがこれらのメソッドの目的です。また、Rubyドキュメントには次のように記載されています。

marshal_dumpを使用すると、マーシャル文字列が小さくなる場合があります。

また、ドキュメントは使用について少し曖昧ですmarshal_dump

オブジェクトをダンプすると、メソッドmarshal_dumpが呼び出されます。marshal_dumpは、marshal_loadがオブジェクトを再構成するために必要な情報を含む結果を返す必要があります。結果は任意のオブジェクトになります。

「結果は、」以外の任意のオブジェクトになる可能性がありますselfself戻ってきたときにルビーが示す動作marshal_dumpが本当に意図的なものなのか(少なくともエラーがあればいいのですが)、それとも実際にはユースケースではないために忘れられただけなのか、私にはわかりません。

于 2013-02-22T17:32:33.307 に答える