2

我有一个这样的结构:

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

我今天发现.list()and[: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

这是有效的,因为 while@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

我认为你应该更好地使用Dash而不是 Struct。看:

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 回答