初始化类(不是对象)的标准方法是什么?
我所做的是创建class_initialize
方法并将其调用
但我是前C#程序员。还有更好的方法吗?
class Specs
class << self
def universal_properties
[:hp, :engine_volume]
end
def compound_universal_properties
[:hp_per_volume]
end
def convertible_properties
[:weight, :torque]
end
def compound_convertible_properties
[:weight_per_hp]
end
private
def define_methods(type)
define_method(type) { instance_variable_get("@#{type}") }
define_method("#{type}=") do |value_and_unit|
send(type).send(:set, value_and_unit)
end
end
def class_initialize
universal_properties.each { |p| define_methods(p) }
convertible_properties.each { |p| define_methods(p) }
compound_universal_properties.each { |p| define_methods(p) }
compound_convertible_properties.each { |p| define_methods(p) }
end
end
class_initialize
public
def initialize
@weight = ConvertibleProperty.new(:weight)
...
end
...
end
不太重要的细节:
我在第一个答案中看到这段代码令人困惑,这对于评论来说太长了。
我不只是创建attr_accessors,因为例如:weight
和:torque
是类ConvertibleProperty
并且具有imperial.value
,imperial.unit
,{{1}等功能}},metric.value
,metric.unit
...
我这样称这个代码:
empty?
当我输入specs = Specs.new
specs.weight = 800, 'kg'
specs.hp = 300
specs.torque = 210, :metric
ruby将其转换为specs.weight = 10, 'kg'
并且我不想用数组specs.weight=([10, 'kg'])
替换权重时,我想在其上调用[10, 'kg']
方法存储原始单位和值,并提供set
和metric
函数,每个函数都返回包含imperial
和value
的结构。
答案 0 :(得分:2)
class Specs
def initialize
instance_exec(&Proc.new) if block_given?
end
def weight!(*args)
weight = ...
end
...
end
specs = Specs.new do
weight! 800, 'kg'
hp! 300
torque! 210, :metric
end
其他方式是指定适当的访问者:
def torque=(*args)
# 210, :metric
@torque = ConvertibleProperty.new(...)
end
如果变量数量很大,可能需要自动创建访问器:
PROPERTIES = {
'UniversalProperty': [:hp, :engine_volume],
'CompoundUniversalProperty': [:hp_per_volume],
'ConvertibleProperty': [:weight, :torque],
'CompoundConvertibleProperty': [:weight_per_hp]
}.freeze
PROPERTIES.each do |type, *props|
props.each do |prop|
attr_reader prop
define_method "#{prop}=" do |*args|
self.instance_variable_set(:"@#{prop}", Kernel.const_get(type).new(*args))
end
end
end
答案 1 :(得分:1)
惯用法,您不会创建以这种方式响应的分配方法,而且这里对元编程没有多大价值。我会首先用简单的术语写出来,然后如果管理你的不同类型变得很麻烦,那么可能稍后重构。
以下是惯用法:
class Specs
def weight
@weight ||= ConvertibleProperty.new(:weight)
end
def torque
@torque ||= ConvertibleProperty.new(:torque)
end
# [..]
end
specs = Specs.new
specs.weight.set(800, 'kg')
specs.torque.set(210, :metric)