当我在ruby中创建类时,我发现自己重复了很多事情,通常我会得到类似于以下内容的东西:
class Foo
attr_reader :bar_0,
:bar_1,
.
.
.
:bar_n
def initialize( bar_0 = something,
bar_1 = something,
.
.
.
bar_n = something)
@bar_0 = bar_0
@bar_1 = bar_1
.
.
.
@bar_n = bar_n
end
end
ruby是否采用了一种快捷方式来更有效地实现这样的东西?
答案 0 :(得分:1)
从问题的表达方式来看,你应该重新考虑你的课程设计。但是,Ruby提供了一种有趣的方法来快速创建具有attr_accessor
s(而不是读者)的类。这是一个简单的例子:
>> class Person < Struct.new(:name, :age) ; end
=> nil
>> p = Person.new
=> #<struct Person name=nil, age=nil>
>> p.age = 23
=> 23
>> p.class
=> Person
>> p.methods.grep(/age/)
=> [:age, :age=]
当然这是一个普通的类,您可以添加所需的所有方法(并使用getter和setter而不是实例变量,例如var
用于getter,self.var = foo
用于setter)。
如果你真的不想要作家,请将它们设为私有或undef
。
>> attrs = [:name, :age]
=> [:name, :age]
>> class Person < Struct.new *attrs ; end
=> nil
>> Person.instance_eval { private *attrs.map{|attr| "#{attr}=" }}
=> Person
>> p = Person.new
=> #<struct Person name=nil, age=nil>
>> p.methods.grep(/age/)
=> [:age]
当然,上述所有内容对initialize
中的大量任务没有帮助,但是人们想知道你是否真的想要很多构造函数参数,或者你是否只有一个哈希参数并将其合并到默认哈希。
答案 1 :(得分:0)
Ruby是动态的,并且在内省方面提供了很多,因此您可以使用元编程(或编写基本上编写代码的代码)。在您的示例中,您可以执行以下操作来清除详细程度:
class Foo
# Rather than writing bar_1, bar_2, bar_3, ...
attr_accessor ((0..9).to_a + ('a'..'n').to_a).map { |x| :"foo_#{x}" }
# Using mass assignment...
def initialize(attributes = {})
attributes.each do |attribute, value|
respond_to?(:"#{attribute}=") && send(:"#{attribute}=", value)
end
end
end
由于质量分配是一种流行且可重复使用的行为,因此将其提取到一个单独的模块并使其成为混合模式是有意义的:
module MassAssignment
def initialize(attributes = {})
mass_assign(attributes)
end
def mass_assign(attributes)
attributes.each do |attribute, value|
respond_to?(:"#{attribute}=") && send(:"#{attribute}=", value)
end
end
end
class Foo
include MassAssignment
end
答案 2 :(得分:0)
您可以使用introduce parameter object重构方法来简化构造函数调用。