2

私はこのような構造体を持っています:

class Item < Struct.new(:url, :list)
  def list
    @list ||= Array.new
  end
end

.list()今日、と[:list]が異なるものを返すことがわかりました。

i = Item.new
#=> #<struct Item url=nil, list=nil>
i.list
#=> []
i[:list]
#=> nil
i.list << 1
#=> [1]
i.list += [2]
#=> [1, 2]
i.list
#=> [1]
i[:list]
#=> [1, 2]

これはなぜですか?また、デフォルトの空の配列を適切に持つように構造体を作成するにはどうすればよいですか?

4

4 に答える 4

2

誰かがすでに「なぜ」のビットに答えているので、それでもこれを実行したい場合は、これをStruct試してみませんか?

class Item < Struct.new(:url, :list)
  def list
    self[:list] ||= Array.new
  end
end

これ@listは、作成のインスタンス変数である一方で、Structそれを提供するアクセサーが独自のものであるために機能します。(:list)。self[:list]あなたはそれを手に入れることができます。

i = Item.new # =>  #<struct Item url=nil, list=nil>
i.list   # => []
i[:list] # => []
# Compare using OBJECT IDENTITY (is i.list internally the same thing as i[:list]?)
i[:list].equal? i.list # true
i.list << 1   # => [1]
i.list += [2] # => [1, 2]
i.list        # => [1, 2]
i[:list]      # => [1, 2]
于 2012-12-04T07:35:06.393 に答える
1

Struct の代わりにDashを使用する方がよいと思います。見て:

require 'hashie'

class Item < Hashie::Dash
  property :url
  property :list, default: []
end

i = Item.new # => #<Item list=[]>
i.list # => []
i[:list] # => []
i.list << 1 # => [1]
i.list += [2] # => [1, 2]
i.list # => [1, 2]
i[:list] # => [1, 2]
于 2012-12-04T07:19:08.147 に答える
1

Sergio Tulentsevがその部分に答えhow can I write my struct to have default empty array properly?ので、その部分を書きますWhy is this?
情報が不足していますが、構造体が書かれています ::new は、指定されたシンボルのアクセサメソッドを含む、aString によって名前が付けられた新しいクラスを作成します。

したがって、アクセサーはありますが、属性:listとはまだ異なり@listます。これは、好きなように名前@listを付けることができ、構造体の に関連付けられないことを意味します:list
また、構造体が以前に提供していたシンボル アクセサーをオーバーライドします。def list; end

i.list << 1   # adding 1 to @list set to Array.new
#=> [1]
i.list += [2] # equals i.list = i.list + [2]
              # i.list= is the `:list` setter method.
              # i.list is the @list getter method.
              # It equals :list = @list + [2]
#=> [1, 2]
i.list        # @list
#=> [1]
i[:list]      # :list
#=> [1, 2]
于 2012-12-04T07:26:11.850 に答える
1

Struct の他の利点が必要で、それに固執する必要があると仮定すると、独自のinitializeメソッドを作成できます。

class Item < Struct.new(:url, :list)
  def initialize(url, list = nil)
    self.url  = url
    self.list = Array(list)
  end
end

Array()渡されたものがまだ配列でない場合は配列に入れられ、 が引数の場合は空の配列 ( [])が返さnilれます。

于 2012-12-04T07:26:23.720 に答える