我很难理解Ruby中的attr_accessor。 有人能给我解释一下吗?


当前回答

假设您有一个类Person。

class Person
end

person = Person.new
person.name # => no method error

显然,我们没有定义方法名。我们来做一下。

class Person
  def name
    @name # simply returning an instance variable @name
  end
end

person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error

啊哈,我们可以读名字,但这并不意味着我们可以分配名字。这是两种不同的方法。前者称为读者,后者称为作者。我们还没有创建写入器,我们来做一下。

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"

太棒了。现在我们可以使用reader和writer方法写入和读取实例变量@name。不过,这是经常做的,为什么每次都浪费时间写这些方法呢?我们可以做得简单些。

class Person
  attr_reader :name
  attr_writer :name
end

即使这样也会重复。当你同时需要读取器和写入器时,只需使用访问器!

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Dennis"
person.name # => "Dennis"

原理是一样的!你猜怎么着:person对象中的实例变量@name将被设置,就像我们手动设置时一样,所以你可以在其他方法中使用它。

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"

就是这样。为了理解attr_reader, attr_writer和attr_accessor方法是如何为你生成方法的,请阅读其他答案,书籍,ruby文档。

其他回答

它只是一个为实例变量定义getter和setter方法的方法。一个示例实现如下:

def self.attr_accessor(*names)
  names.each do |name|
    define_method(name) {instance_variable_get("@#{name}")} # This is the getter
    define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
  end
end

Attr_accessor非常简单:

attr_accessor :foo

是以下操作的快捷方式:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

它只不过是一个对象的getter/setter

Attr_accessor(如@pst所述)只是一个方法。它的作用是为你创建更多的方法。

这段代码:

class Foo
  attr_accessor :bar
end

等价于下面的代码:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

你可以自己用Ruby编写这样的方法:

class Module
  def var( method_name )
    inst_variable_name = "@#{method_name}".to_sym
    define_method method_name do
      instance_variable_get inst_variable_name
    end
    define_method "#{method_name}=" do |new_value|
      instance_variable_set inst_variable_name, new_value
    end
  end
end

class Foo
  var :bar
end

f = Foo.new
p f.bar     #=> nil
f.bar = 42
p f.bar     #=> 42

The main functionality of attr_accessor over the other ones is the capability of accessing data from other files. So you usually would have attr_reader or attr_writer but the good news is that Ruby lets you combine these two together with attr_accessor. I think of it as my to go method because it is more well rounded or versatile. Also, peep in mind that in Rails, this is eliminated because it does it for you in the back end. So in other words: you are better off using attr_acessor over the other two because you don't have to worry about being to specific, the accessor covers it all. I know this is more of a general explanation but it helped me as a beginner.

希望这对你有所帮助!

我是ruby的新手,不得不理解下面的奇怪之处。也许将来能帮到别人。最后,就像上面提到的,其中两个函数(def myvar, def myvar=)都隐式地访问@myvar,但是这些方法可以被局部声明覆盖。

class Foo
  attr_accessor 'myvar'
  def initialize
    @myvar = "A"
    myvar = "B"
    puts @myvar # A
    puts myvar # B - myvar declared above overrides myvar method
  end

  def test
    puts @myvar # A
    puts myvar # A - coming from myvar accessor

    myvar = "C" # local myvar overrides accessor
    puts @myvar # A
    puts myvar # C

    send "myvar=", "E" # not running "myvar =", but instead calls setter for @myvar
    puts @myvar # E
    puts myvar # C
  end
end