【问题标题】:Access instance variable using its name (as symbol)使用名称(作为符号)访问实例变量
【发布时间】:2011-07-25 16:09:09
【问题描述】:

在 Ruby 中,我有这个类:


class Position
  attr_reader :x, :y
  def initialize(x, y)
      @x, @y = x, y
  end
end
我想做的是使用符号访问 x 和 y 变量,如下所示:
axis = :x
pos = Position.new(5,6)
 #one way:
pos.axis # 5 (pos.x)
 #other way:
pos.get(axis) # 5 (pos.x)

感谢this question 我找到了这段代码,我可以实现第二种行为。

#...
class Position
  def get(var)
    instance_variable_get(("@#{var}").intern)
  end
end
但它看起来丑陋且效率低下(尤其是将符号转换为字符串并返回符号)。有没有更好的办法?

【问题讨论】:

  • xy 不是变量,而是方法:-)
  • 对,我还是习惯了。 :)

标签: ruby class variables


【解决方案1】:

简单,使用send方法

class Position
  attr_reader :x, :y

  def initialize(x, y)
    @x, @y = x, y
  end
end
 => nil 

pos = Position.new(5,5)
 => #<Position:0x0000010103d660 @x=5, @y=5> 

axis = :x
 => :x 

pos.send axis
 => 5 

【讨论】:

  • 无需将axis 转换为字符串。 axis 是 Symbol,在.send 中,方法名必须作为 Symbol 传递。 => pos.send(axis)
  • 这实际上并不访问实例变量,它只是调用访问器。
【解决方案2】:

以下是两种技术的结合方式。假设我们已经有了你的类定义,

position = Position.new(1, 2)
axis = :x
position.send axis #=> 1
axis = :y
position.send axis #=> 2

Object#send 方法至少接受一个符号,表示要调用的方法的名称,然后调用它。您也可以在名称和块之后将参数传递给方法。

第二种方法(使用您的Position#get 方法)是

class Position
  def get(axis)
    send axis
  end
end

position = Position.new(1, 2)
axis = :x
position.get axis #=> 1
axis = :y
position.get axis #=> 2

我推荐这种方式,因为它封装了获取值的技术。如果以后需要更改,则不需要更改所有使用Position 的代码。

【讨论】:

    猜你喜欢
    • 2012-07-16
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多