我有这样的结构:
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]
为什么这样,我如何编写我的结构以正确地使用默认空数组?
答案 0 :(得分: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]
答案 1 :(得分: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]
答案 2 :(得分:1)
Sergio Tulentsev answered how can I write my struct to have default empty array properly?
部分,所以我会写Why is this?
部分。
我缺少信息,但有一个结构,它写成::new creates a new class, named by aString, containing accessor methods for the given symbols.
因此,您拥有: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]
答案 3 :(得分: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
)。