【问题标题】:Ruby: How should I access instance variables inside a class?Ruby:我应该如何访问类中的实例变量?
【发布时间】:2023-03-16 20:36:01
【问题描述】:

在 ruby​​ 中,您可以通过 @var_name 或私有 getter attr_reader :var_name 在内部直接访问变量。

哪个解决方案更(语义上?)正确?使用解决方案 1 或解决方案 2 的任何优点/缺点?

解决方案 1:

class Point
 def initialize(x, y)
   @x = x
   @y = y
 end

 def distance
   Math.sqrt(@x ** 2 + @y ** 2)
 end
end

解决方案 2:

class Point
  def initialize(x, y)
   @x = x
   @y = y
  end

  def distance
    Math.sqrt(x ** 2 + y ** 2)
  end

private 
  attr_reader :x, :y

end

【问题讨论】:

  • 有时您想使用“解决方案 3”:Object#instance_variable_get。例如,假设您想要计算所有实例变量值的平方和。你可以写def sum_of_squares; instance_variables.reduce(0) { |t,v| t + instance_variable_get(v) ** 2 }; end,然后写Point.new(3,5).sum_of_squares #=> 34Object#instance_variables 返回实例变量的数组。
  • @CarySwoveland 这很棘手,我喜欢它!我相信这种方法非常适合codegolf.stackexchange.com :D
  • attr_reader 只是避免为每个属性编写相同、简单和通用的 getter 方法的捷径。它是 DRY 的一部分,imo。
  • @c650 这不仅仅是一个快捷方式。它是 C 扩展,比手动编写方法快几倍。 omniref.com/ruby/2.2.0/files/…
  • @FilipBartuzi 我听说了。然而,对我来说,如果您使用的是 Ruby,那么您可能不会关心额外的几秒钟。如果您真的关心速度,您不会使用不同的语言吗?

标签: ruby class oop object design-patterns


【解决方案1】:

我会使用第二个选项:

class Point
  def initialize(x, y)
   @x = x
   @y = y
  end

  def distance
    Math.sqrt(x ** 2 + y ** 2)
  end

private 

  attr_reader :x, :y    
end

有两个原因:

  1. attr_reader 可能是 faster(正如 Filip Bartuzi 已经指出的那样)
  2. 使用attr_reader 可能会在以后通过将attr_reader 替换为自定义getter 方法来更轻松地重构该类。

【讨论】:

  • 很好的解决方案。我能想到第三个原因。看看我在这个问题上留下的评论。另一种方法是def sum_of_squares; instance_variables.reduce(0) { |t,sym| t + send(sym.to_s[1..-1]) ** 2 }; end,然后是Point.new(3,5).sum_of_squares #=> 34。对于每个实例变量,这会将其 getter 的字符串表示形式发送到实例以获取实例变量的值。
【解决方案2】:

attr_reader :x, :y 定义了以下函数:

def x
  @x
end

def y
  @y
end

所以这两种方法是等价的,实际上是相同的。在这两种情况下,性能也是similar,尽管attr_reader 比其他一些变量访问方法可以是faster..

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 2015-12-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 2020-03-15
  • 2014-12-03
相关资源
最近更新 更多