根据文档,未设置的Struct属性设置为nil:
unset参数默认为nil.
是否可以为特定属性指定默认值?
例如,对于以下Struct
Struct.new("Person", :name, :happy)
Run Code Online (Sandbox Code Playgroud)
我希望该属性happy默认为true而不是nil.我怎样才能做到这一点?如果我这样做
Struct.new("Person", :name, :happy = true)
Run Code Online (Sandbox Code Playgroud)
我明白了
-:1: syntax error, unexpected '=', expecting ')'
Struct.new("Person", :name, :happy = true)
^
-:1: warning: possibly useless use of true in void context
Run Code Online (Sandbox Code Playgroud)
rin*_*aun 23
这也可以通过将Struct创建为子类并initialize使用默认值覆盖来实现,
如以下示例所示:
class Person < Struct.new(:name, :happy)
def initialize(name, happy=true); super end
end
Run Code Online (Sandbox Code Playgroud)
一方面,这种方法确实导致了一些样板; 另一方面,它做你正在寻找的美好和简洁.
一个副作用(可能是一个好处或一个烦恼,取决于你的偏好/用例)是你失去默认Struct行为的所有属性的默认行为nil- 除非你明确地设置它们.实际上,name除非您将其声明为,否则上面的示例将生成必需的参数name=nil
6ft*_*Dan 11
在@ rintaun的示例之后,您还可以使用Ruby 2+中的关键字参数执行此操作
A = Struct.new(:a, :b, :c) do
def initialize(a:, b: 2, c: 3); super end
end
A.new
# ArgumentError: missing keyword: a
A.new a: 1
# => #<struct A a=1, b=2, c=3>
A.new a: 1, c: 6
# => #<struct A a=1, b=2, c=6>
Run Code Online (Sandbox Code Playgroud)
UPDATE
现在需要编写如下代码才能工作.
A = Struct.new(:a, :b, :c) do
def initialize(a:, b: 2, c: 3)
super(a, b, c)
end
end
Run Code Online (Sandbox Code Playgroud)
@Linuxios 给出了一个覆盖成员查找的答案。这有几个问题:您不能显式地将成员设置为零,并且每个成员引用都会产生额外的开销。在我看来,您实际上只想在使用提供给::newor的部分成员值初始化新的结构对象时提供默认值::[]。
这是一个使用附加工厂方法扩展 Struct 的模块,该方法允许您使用散列描述所需的结构,其中键是成员名称,以及在初始化时未提供时默认填充的值:
# Extend stdlib Struct with a factory method Struct::with_defaults
# to allow StructClasses to be defined so omitted members of new structs
# are initialized to a default instead of nil
module StructWithDefaults
# makes a new StructClass specified by spec hash.
# keys are member names, values are defaults when not supplied to new
#
# examples:
# MyStruct = Struct.with_defaults( a: 1, b: 2, c: 'xyz' )
# MyStruct.new #=> #<struct MyStruct a=1, b=2, c="xyz"
# MyStruct.new(99) #=> #<struct MyStruct a=99, b=2, c="xyz">
# MyStruct[-10, 3.5] #=> #<struct MyStruct a=-10, b=3.5, c="xyz">
def with_defaults(*spec)
new_args = []
new_args << spec.shift if spec.size > 1
spec = spec.first
raise ArgumentError, "expected Hash, got #{spec.class}" unless spec.is_a? Hash
new_args.concat spec.keys
new(*new_args) do
class << self
attr_reader :defaults
end
def initialize(*args)
super
self.class.defaults.drop(args.size).each {|k,v| self[k] = v }
end
end.tap {|s| s.instance_variable_set(:@defaults, spec.dup.freeze) }
end
end
Struct.extend StructWithDefaults
Run Code Online (Sandbox Code Playgroud)