2

在Ruby中,有没有办法做类似的事情

class Foo
    attr_reader :var_name :reader_name #This won't work, of course
    def initialize
        @var_name = 0
    end
end

# stuff here ....

def my_method
    foo = Foo.new
    assert_equal 0,foo.reader_name
end

换句话说,是否有一种标准方法可以为使用与变量不同的名称的变量创建访问器方法。(当然,除了手动编码。)

4

3 回答 3

4

您不能将任何选项传递给 attr_reader

这是手工编码吗?

class Foo
  def initialize
      @var_name = 0
  end
  def reader_name; @var_name; end
end
于 2011-04-24T18:48:05.820 回答
4

你可以使用alias_method

class Foo
  attr_reader :var_name
  alias_method :reader_name, :var_name
  def initialize
    @var_name = 0
  end
end

var_name尽管如此,构建的方法attr_reader仍然可用。如果你真的想的话,你可以使用remove_method来摆脱这个var_name方法(但要确保你以正确的顺序得到所有东西):

class Foo
  attr_reader :var_name
  alias_method :reader_name, :var_name
  remove_method :var_name
  def initialize
    @var_name = 0
  end
end

如果你真的想,你可以猴子修补一个attr_reader_as方法到模块中:

class Module
  def attr_reader_as(attr_name, alias_name)
    attr_reader attr_name
    alias_method alias_name, attr_name
    remove_method attr_name
  end
end

class Foo
  attr_reader_as :var_name, :reader_name
  def initialize
    @var_name = 0
  end
end

更好attr_reader_as的方法是使用哈希(例如{ var_name: :reader_name, var_name: :reader_name2}),但我将把它作为练习留给读者。

于 2011-04-24T19:02:05.033 回答
3

首先,我的口头禅:一个好的程序员会很好地扮演他的队友。遵循惯例就是在发挥别人的好。

你想要的似乎不合常规,正如@edgerunner 所说,这是不好的做法(阅读:我会打你的)。我要说的是,三思而后行,我不知道你的用例,它可能证明是有效的......无论如何,应该允许复活节期间有一点乐趣,所以我练习了一些元编程并使用了 Mixins。

class Foo
  include MyAttrReader
  my_attr_reader :var_name, :reader_name
  def initialize
    @var_name = 0
  end
end

很干净。该模块可以解决问题(确保在上课之前加载此模块)

module MyAttrReader
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def my_attr_reader(attribute, read_attribute)
      define_method "#{read_attribute}" do
        instance_variable_get "@#{attribute}"
      end
    end
  end
end

在 irb 中测试

ruby-1.9.2-p180 :001 > load 'my_attr_reader.rb'
 => true 
ruby-1.9.2-p180 :002 > load 'foo.rb'
 => true 
ruby-1.9.2-p180 :003 > f = Foo.new
 => #<Foo:0x00000100979658 @var_name=0> 
ruby-1.9.2-p180 :004 > f.reader_name
 => 0 
ruby-1.9.2-p180 :005 > f.var_name
NoMethodError: undefined method `var_name' for #<Foo:0x00000100979658 @var_name=0>

我希望你看到这对其他人来说是多么不直观。您可以重写 to_s 方法以显示如何访问@var_name,但我不会去那里......或者也定义 var_name 方法(两个 getter 方法)。遵守约定。总之,我玩得很开心,祝你好运!

于 2011-04-24T20:44:47.820 回答