Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 有没有办法让attr_reader使用与实例变量不同的名称创建方法?_Ruby_Attributes_Conventions_Standard Library - Fatal编程技术网

Ruby 有没有办法让attr_reader使用与实例变量不同的名称创建方法?

Ruby 有没有办法让attr_reader使用与实例变量不同的名称创建方法?,ruby,attributes,conventions,standard-library,Ruby,Attributes,Conventions,Standard Library,在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 换句话说,是否有一种

在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

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

您不能将任何选项传递给attr\u reader

这是手工编码吗

class Foo
  def initialize
      @var_name = 0
  end
  def reader_name; @var_name; end
end
您可以使用:

attr\u reader
构建的
var\u name
方法仍然可用。如果你真的想,你可以使用
var\u name
方法来摆脱它(但要确保一切都按正确的顺序进行):

如果您真的愿意,您可以将
attr\u reader\u 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\u reader\u as
需要一个散列(例如
{var\u name::reader\u name,var\u name::reader\u name2}
),但我将把它作为一个练习留给读者。

首先,我的咒语是:一个好的程序员会让他的队友玩得好。以下惯例对其他人有好处。

你想要的似乎是非传统的,正如@edgerunner所说的,是糟糕的做法(读:我会揍你的)。我想说的是,仔细想想,我不知道你的用例,它可能被证明是有效的。。。无论如何,复活节期间的一点乐趣应该是允许的,所以我练习了一些元编程并玩了混音游戏

class Foo
  include MyAttrReader
  my_attr_reader :var_name, :reader_name
  def initialize
    @var_name = 0
  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>
ruby-1.9.2-p180:001>加载'my_attr_reader.rb'
=>正确
ruby-1.9.2-p180:002>加载“foo.rb”
=>正确
ruby-1.9.2-p180:003>f=Foo.new
=> # 
ruby-1.9.2-p180:004>f.reader\u名称
=> 0 
ruby-1.9.2-p180:005>f.var_名称
NoMethodError:未定义的方法“var_name”#

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

你为什么要这么做?当您的内部名称与外部接口规范不同时,这可能是一种不好的做法。这是在ruby koan的about_dice_项目中出现的。他们想调用最近形成的掷骰子列表
。我想叫它
@lastRolled
。一个是指它的实现方式(作为一个内部变量应该如此),另一个是指说明符对它的思考方式。在这种情况下,这一点都不重要,但我可以看到这是我将来可能想知道的事情。投票给写得好的Q。我不必喜欢你的要求;)+1代表“不要这么懒,自己动手”。很抱歉破坏了你酷炫幸运的8888的声誉。是的,这是手工编码。但您的回答让我知道,大多数ruby程序员可能会这样做。当然
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
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>