我很难理解Ruby中的attr_accessor。 有人能给我解释一下吗?
当前回答
我认为让新手和程序员(比如我自己)困惑的部分原因是:
“为什么我不能告诉实例它有任何给定的属性(例如,名称),并一次性为该属性赋值?”
更一般化一点,但这就是我的想法:
考虑到:
class Person
end
我们还没有将Person定义为可以有名称或任何其他属性的东西。
那么如果我们
baby = Person.new
...试着给它们起个名字…
baby.name = "Ruth"
我们得到一个错误,因为在Rubyland中,对象的Person类不是与“名称”相关联或不具有“名称”的东西……然而!
但是我们可以使用任何给定的方法(参见前面的回答)来说明,“Person类(baby)的实例现在可以有一个名为'name'的属性,因此我们不仅有了获取和设置该名称的语法方法,而且这样做对我们来说是有意义的。”
再一次,从一个稍微不同和更一般的角度来解决这个问题,但我希望这有助于Person类的下一个实例找到这个线程的方法。
其他回答
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
它只是一个为实例变量定义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
我认为让新手和程序员(比如我自己)困惑的部分原因是:
“为什么我不能告诉实例它有任何给定的属性(例如,名称),并一次性为该属性赋值?”
更一般化一点,但这就是我的想法:
考虑到:
class Person
end
我们还没有将Person定义为可以有名称或任何其他属性的东西。
那么如果我们
baby = Person.new
...试着给它们起个名字…
baby.name = "Ruth"
我们得到一个错误,因为在Rubyland中,对象的Person类不是与“名称”相关联或不具有“名称”的东西……然而!
但是我们可以使用任何给定的方法(参见前面的回答)来说明,“Person类(baby)的实例现在可以有一个名为'name'的属性,因此我们不仅有了获取和设置该名称的语法方法,而且这样做对我们来说是有意义的。”
再一次,从一个稍微不同和更一般的角度来解决这个问题,但我希望这有助于Person类的下一个实例找到这个线程的方法。
尽管已有大量的答案,但在我看来,没有一个能解释这里涉及的实际机制。它的元编程;它利用了以下两个事实:
您可以动态地修改模块/类 模块/类声明本身就是可执行代码
好吧,想象一下:
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非常简单:
attr_accessor :foo
是以下操作的快捷方式:
def foo=(val)
@foo = val
end
def foo
@foo
end
它只不过是一个对象的getter/setter
推荐文章
- 了解Gemfile。锁文件
- 如何确定一个数组是否包含另一个数组的所有元素
- 是什么导致这个ActiveRecord::ReadOnlyRecord错误?
- 最好的打印散列的方法
- Rails:dependent =>:destroy VS:dependent =>:delete_all
- 我可以在不包含Ruby模块的情况下调用实例方法吗?
- 如何将新项目添加到哈希
- 测试一个Ruby类是否是另一个类的子类
- 什么时候使用Struct vs. OpenStruct?
- 数组到哈希Ruby
- 我如何让红宝石打印一个完整的回溯而不是截断一个?
- 如何使用RSpec的should_raise与任何类型的异常?
- 如何创建退出消息
- 忽略GEM,因为没有构建它的扩展
- 在Gem::Specification.reset期间未解决的规格: