使用其名称(作为符号)访问实例变量

jnv*_*jnv 6 ruby variables class

在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)

感谢我在这段代码中发现的这个问题,我可以实现第二种行为.

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

Wes*_*Wes 8

容易,使用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 
Run Code Online (Sandbox Code Playgroud)

  • 这实际上并不访问实例变量,它只是调用访问器。 (2认同)

Tom*_*Tom 3

以下是执行这两种技术的方法。假设我们已经有了你的类定义,

position = Position.new(1, 2)
axis = :x
position.send axis #=> 1
axis = :y
position.send axis #=> 2
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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