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


当前回答

基本上,它们伪造了Ruby所不具备的公开可访问的数据属性。

其他回答

基本上,它们伪造了Ruby所不具备的公开可访问的数据属性。

假设您有一个类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文档。

尽管已有大量的答案,但在我看来,没有一个能解释这里涉及的实际机制。它的元编程;它利用了以下两个事实:

您可以动态地修改模块/类 模块/类声明本身就是可执行代码

好吧,想象一下:

class Nameable
  def self.named(whatvalue)
    define_method :name do whatvalue end
  end
end

我们声明了一个名为which的类方法,当用值调用时,创建一个名为name的实例方法,该实例方法返回该值。这就是元编程的部分。

现在我们将子类化这个类:

class Dog < Nameable
  named "Fido"
end

我们刚才到底做了什么?在类声明中,可执行代码执行时引用了类。因此,简单的单词named实际上是对类方法named的调用,它继承自Nameable;我们传递字符串“Fido”作为参数。

命名的类方法是做什么的?它创建一个名为name的实例方法,该方法返回该值。现在,在幕后,Dog有一个这样的方法:

def name
   "Fido"
end

不相信我?然后看这个小动作:

puts Dog.new.name #=> Fido

我为什么要告诉你这些?因为我刚才对Nameable所做的和attr_accessor对Module所做的几乎完全一样。当您使用attr_accessor时,您正在调用创建实例方法的类方法(继承自Module)。特别是,它为实例属性创建了一个getter和setter方法,实例属性的名称是您提供的参数,这样您就不必自己编写这些getter和setter方法。

简单地说,它将为类定义setter和getter。

请注意,

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

So

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

等效于为类定义setter和getter。

属性访问器attr_accessor提供了两个免费方法。

就像在Java中,它们被称为getter和setter。

很多答案都给出了很好的例子,所以我就简单点。

# the_attribute

and

# the_attribute =

在旧的ruby文档中,#表示方法。 它还可以包含一个类名前缀… MyClass # my_method