我很难理解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文档。
其他回答
attrr -accessor简单地为指定的属性创建getter和setter方法
Attr_accessor只是一个方法。(这个链接应该提供更多关于它如何工作的见解——看看生成的方法对,一个教程应该告诉你如何使用它。)
关键在于,类在Ruby中不是定义(在c++和Java等语言中“只是定义”),而是求值的表达式。在此求值期间,调用attr_accessor方法,该方法反过来修改当前类——记住隐式接收器:self。其中self是此时“打开”的类对象。
对attr_accessor和friends的需求是:
像Smalltalk一样,Ruby不允许在该对象的method1之外访问实例变量。也就是说,不能像在Java甚至Python中那样以x.y形式访问实例变量。在Ruby中,y总是被当作一个要发送的消息(或“要调用的方法”)。因此attr_*方法创建包装器,通过动态创建的方法代理实例@变量访问。 样板很糟糕
希望这能澄清一些细节。快乐的编码。
1严格来说,这并不正确,有一些“技术”围绕这一点,但没有语法支持“公共实例变量”访问。
如果你熟悉面向对象的概念,你必须熟悉getter和setter方法。 在Ruby中attr_accessor做同样的事情。
Getter和Setter的一般方式
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
Setter方法
def name=(val)
@name = val
end
Getter方法
def name
@name
end
在Ruby中的Getter和Setter方法
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
尽管已有大量的答案,但在我看来,没有一个能解释这里涉及的实际机制。它的元编程;它利用了以下两个事实:
您可以动态地修改模块/类 模块/类声明本身就是可执行代码
好吧,想象一下:
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方法。
嗯。很多很好的答案。这是我的一些看法。
attr_accessor是一个简单的方法,可以帮助我们清理(DRY-ing)重复的getter和setter方法。 这样我们就可以更专注于编写业务逻辑而不用担心setter和getter。
推荐文章
- 无法安装gem -未能建立gem本地扩展-无法加载这样的文件——mkmf (LoadError)
- 如何在Ruby中创建文件
- 什么是Ruby文件。开放模式和选项?
- Ruby数组到字符串的转换
- 如何分割(块)一个Ruby数组成X元素的部分?
- Ruby中“or”和||的区别?
- 如何测试参数是否存在在轨道
- 在Ruby中不创建新字符串而修饰字符串的规范方法是什么?
- RVM不是一个函数,用' RVM use…’不会起作用
- 了解Gemfile。锁文件
- 如何确定一个数组是否包含另一个数组的所有元素
- 是什么导致这个ActiveRecord::ReadOnlyRecord错误?
- 最好的打印散列的方法
- Rails:dependent =>:destroy VS:dependent =>:delete_all
- 我可以在不包含Ruby模块的情况下调用实例方法吗?