【问题标题】:How can I avoid using class variables in Ruby如何避免在 Ruby 中使用类变量
【发布时间】:2017-06-11 11:41:47
【问题描述】:

我有一段使用类变量的代码。我读过在 Ruby 中通常应该避免使用类变量。

类变量是@@cost@@kwh

如何在不使用类变量的情况下重写以下内容?

class Device
 attr_accessor :name, :watt

 @@cost = 0.0946

 def initialize(name, watt)
   @name = name
   @watt = watt
 end

  def watt_to_kwh(hours)
    @@kwh = (watt / 1000) * hours
  end

  def cost_of_energy
    puts "How many hours do you use the #{self.name} daily?"
  hours = gets.chomp.to_i
    self.watt_to_kwh(hours)
    daily_cost = @@kwh * @@cost
    montly_cost = daily_cost * 30
    puts "Dayly cost: #{daily_cost}€"
    puts "montly_cost: #{montly_cost}€"
  end
end

【问题讨论】:

  • 为什么@@kwh 是一个类变量?
  • 我相信montly_cost 应该是monty_cost,假设它涉及到巨蟒的飞行马戏团。

标签: ruby class-variables


【解决方案1】:

@@cost 的行为更像一个常量(即它不会在运行时改变),所以你应该改用一个:

COST = 0.0946

@@kwh 应该是一个实例变量,因为它只在实例化对象中使用,所以你可以使用@kwh 代替:

@kwh = (watt / 1000) * hours

daily_cost = @@kwh * @@cost 将变为:

daily_cost = @kwh * COST

这将避免使用类变量,但您也可以完全消除 @kwh,因为您不会在其他任何地方使用它。

所以,而不是:

def watt_to_kwh(hours)
  @kwh = (watt / 1000) * hours
end

你可以这样做:

def watt_to_kwh(hours)
  (watt / 1000) * hours
end

并在cost_of_energy 方法中像这样使用它:

def cost_of_energy
  puts "How many hours do you use the #{self.name} daily?"
  hours = gets.chomp.to_i
  daily_cost = watt_to_kwh(hours) * COST
  montly_cost = daily_cost * 30
  puts "Dayly cost: #{daily_cost}€"
  puts "montly_cost: #{montly_cost}€"
end

【讨论】:

  • 在发布之前,我实际上已经创建了两个实例变量,但是没有成功,我收到了 *': nil can't be coerced into Integer TypeError。现在我看到将Cost 设为局部变量是我收到错误的原因。但为什么?为什么@kwh 有效而@cost 无效?
  • @johnlock1 你是如何设置@cost = 0.0946的?它应该设置在initialize 方法(或任何其他实例方法)中。
  • @gery 好的,所以为了使用实例变量,我必须在方法中设置它?没看懂,多谢解惑!
  • @johnlock1 可以,否则实例化对象将无法使用。
【解决方案2】:

试试这个。

class Device
  singleton_class.send(:attr_accessor, :cost_per_kwh)

  def initialize(name, watts)
    @name = name
    @watts = watts
  end

  def daily_cost(hours_per_day)
    self.class.cost_per_kwh * kwh_per_day(hours_per_day)
  end

  def monthly_cost(hours_per_day)
    30 * daily_cost(hours_per_day)
  end

  private

  def kwh_per_day(hours_per_day)
    hours_per_day * @watts / 1000
  end
end

singleton_class.send(:attr_accessor, :cost_per_kwh) 为类实例变量@cost_per_kwh 创建一个setter 和getter。

首先,获取并保存每千瓦时的成本,该成本将用于计算所有感兴趣的设备的成本。

puts "Please enter the cost per kwh in $"    
Device.cost_per_kwh = gets.chomp.to_f

假设

Device.cost_per_kwh = 0.0946

计算每个感兴趣的设备的成本。

puts "What is the name of the device?"
name = gets.chomp

puts "How many watts does it draw?"
watts = gets.chomp.to_f

假设

name = "chair"
watts = 20000.0

我们现在可以创建一个类实例。

device = Device.new(name, watts)
  #=> #<Device:0x007f9d530206f0 @name="chair", @watts=20000.0> 

最后,获取每天的小时数,这是未来计算给定设备的成本时唯一可能发生变化的变量。

puts "How many hours do you use the #{name} daily?"
hours_per_day = gets.chomp.to_f

最后,假设

hours_per_day = 0.018

然后我们可以计算成本。

puts "Daily cost: $#{ device.daily_cost(hours_per_day)}"
Daily cost: $0.034056€

puts "Monthly_cost (30 days/month): $#{ 30 * device.daily_cost(hours_per_day) }"
Monthly_cost (30 days/month): $1.0216800000000001

假设情况发生变化1并且设备的使用增加。我们只需要每天更新小时数。例如,

puts "How many hours do you use the #{name} daily?"
hours_per_day = gets.chomp.to_f

现在假设

hours_per_day = 1.5

然后

puts "Daily cost: $#{ device.daily_cost(hours_per_day)}"    
Daily cost: $2.838

puts "Monthly_cost (30 days/month): $#{ 30 * device.daily_cost(hours_per_day) }"
Monthly_cost (30 days/month): $85.14

1例如选举新总统。

【讨论】:

  • 不错!我喜欢singleton_class 来避免(硬编码)常量。
猜你喜欢
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2014-10-07
  • 2017-01-03
  • 2012-09-03
  • 1970-01-01
相关资源
最近更新 更多