这是一个重新设计的、Ruby 化的代码版本,它完全避免了使用这些变量的需要。如果你看这里的操作你并不关心,特别是元素是什么,你只关心它的价值和每单位重量的相对丰度。
重组后的 Element 类如下所示:
class Element
attr_reader :symbol
attr_reader :price
attr_reader :amount
def initialize(symbol, price, amount)
# Cocerce both inputs into floats
@symbol = symbol
@price = price.to_f
@amount = amount.to_f
end
end
现在它包含了对元素本身很重要的信息,比如它的符号。将符号保留在变量名之类的地方实际上很烦人,因为变量名不应该具有那样的重要含义,它们应该只是为了便于阅读。
现在您可以在一个容器对象中一次性定义所有元素:
ELEMENTS = [
Element.new('O', 0.30, 0.65),
Element.new('C', 2.40, 0.18),
Element.new('H', 12, 0.10),
Element.new('N', 0.40, 0.03),
Element.new('Ca', 11, 0.015),
Element.new('P', 4, 0.01),
Element.new('K', 85, 0.0035),
Element.new('S', 0.25, 0.0025),
Element.new('Cl', 0.15, 0.0015),
Element.new('Na', 7, 0.0015)
]
生成的可执行文件也可以进一步精简,尤其是在输入转换方面:
# Take input from the command-line to make re-running this easier
pounds = ARGV[0].to_i
# Quick conversion in one shot. Try and keep variables all lower_case
kg = pounds * 0.4536 * 1000
现在您需要做的就是将该表中的每个元素转换为基于权重的净价:
# Convert each element into its equivalent value by weight
total = ELEMENTS.map do |element|
element.price * element.amount * kg
end.reduce(:+) # Added together
这里的reduce 是对不必要的Array 方法的替代。它可以满足您的需要。 Rails 实际上有一个更简单的sum 方法。
然后呈现:
puts "You are worth: $#{(total / 100).round(2)}"
就是这样。
有了这个新结构,您可以根据需要扩展功能,按元素提供详细的价格细分,所有必要的信息都包含在 element 对象中。这就是为什么更独立的对象设计更好。