我很难理解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文档。
其他回答
另一种理解它的方法是通过attr_accessor找出它消除了哪些错误代码。
例子:
class BankAccount
def initialize( account_owner )
@owner = account_owner
@balance = 0
end
def deposit( amount )
@balance = @balance + amount
end
def withdraw( amount )
@balance = @balance - amount
end
end
有以下几种方法:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
下面的方法会抛出错误:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
从技术上讲,Owner和balance不是一个方法,而是一个属性。BankAccount类没有def owner和def balance。如果是,那么您可以使用下面的两个命令。但这两个方法都不存在。但是,您可以访问属性,就像通过attr_accessor访问方法一样!!因此有了attr_accessor这个词。属性。访问器。它像访问方法一样访问属性。
添加attr_accessor:balance,:owner允许你读写balance和owner“method”。现在您可以使用最后两个方法。
$ bankie.balance
$ bankie.owner
attrr -accessor简单地为指定的属性创建getter和setter方法
我也遇到过这个问题,并写了一篇有点冗长的回答。关于这个问题已经有了一些很好的答案,但如果有人想进一步澄清,我希望我的答案能有所帮助
初始化方法
Initialize允许您在创建实例时将数据设置为对象的实例,而不是每次创建类的新实例时都必须在代码中的单独一行中设置数据。
class Person
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
person = Person.new("Denis")
puts person.greeting
在上面的代码中,我们使用initialize方法通过initialize中的参数传递Dennis来设置名称“Denis”。如果我们想在不使用initialize方法的情况下设置名称,可以这样做:
class Person
attr_accessor :name
# def initialize(name)
# @name = name
# end
def greeting
"Hello #{name}"
end
end
person = Person.new
person.name = "Dennis"
puts person.greeting
在上面的代码中,我们使用person.name调用attr_accessor setter方法来设置名称,而不是在初始化对象时设置值。
这两个“方法”都做这个工作,但初始化节省了我们的时间和代码行数。
这是初始化的唯一工作。不能将initialize作为方法调用。要实际获取实例对象的值,需要使用getter和setter (attr_reader (get)、attr_writer(set)和attr_accessor(两者))。请参阅下面的详细信息。
getter, Setters (attr_reader, attr_writer, attr_accessor)
getter, attr_reader: getter的全部目的是返回特定实例变量的值。请访问下面的示例代码以了解这方面的详细信息。
class Item
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
def item_name
@item_name
end
def quantity
@quantity
end
end
example = Item.new("TV",2)
puts example.item_name
puts example.quantity
在上面的代码中,您在Item“example”的实例上调用方法“item_name”和“quantity”。“举例”。Item_name和example。Quantity”将返回(或“获取”)传递到“示例”中的参数值,并将它们显示在屏幕上。
幸运的是,在Ruby中有一个固有的方法,可以让我们更简洁地编写代码;attr_reader方法。请参阅下面的代码;
class Item
attr_reader :item_name, :quantity
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
end
item = Item.new("TV",2)
puts item.item_name
puts item.quantity
这种语法的工作方式完全相同,只是它为我们节省了6行代码。想象一下,如果您有5个可归属于Item类的状态?代码很快就会变长。
Setters, attr_writer: setter方法最初让我感到困惑的是,在我看来,它执行的功能与initialize方法相同。下面我将根据我的理解来解释两者的区别;
如前所述,initialize方法允许您在对象创建时设置对象实例的值。
但是,如果您想稍后(在实例创建之后)设置这些值,或者在初始化后更改它们,该怎么办呢?这是一个使用setter方法的场景。这就是区别。在最初使用attr_writer方法时,不必“设置”特定的状态。
下面的代码是使用setter方法为Item类的这个实例声明值item_name的示例。注意,我们继续使用getter方法attr_reader,这样我们就可以获取值并将它们打印到屏幕上,以防您想自己测试代码。
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
下面的代码是使用attr_writer来再次缩短代码并节省时间的示例。
class Item
attr_reader :item_name
attr_writer :item_name
end
item = Item.new
puts item.item_name = "TV"
下面的代码重复了上面的初始化示例,其中我们使用initialize在创建时设置对象item_name的值。
class Item
attr_reader :item_name
def initialize(item_name)
@item_name = item_name
end
end
item = Item.new("TV")
puts item.item_name
attr_accessor:执行attr_reader和attr_writer的函数,为您节省了多一行代码。
基本上,它们伪造了Ruby所不具备的公开可访问的数据属性。
我认为让新手和程序员(比如我自己)困惑的部分原因是:
“为什么我不能告诉实例它有任何给定的属性(例如,名称),并一次性为该属性赋值?”
更一般化一点,但这就是我的想法:
考虑到:
class Person
end
我们还没有将Person定义为可以有名称或任何其他属性的东西。
那么如果我们
baby = Person.new
...试着给它们起个名字…
baby.name = "Ruth"
我们得到一个错误,因为在Rubyland中,对象的Person类不是与“名称”相关联或不具有“名称”的东西……然而!
但是我们可以使用任何给定的方法(参见前面的回答)来说明,“Person类(baby)的实例现在可以有一个名为'name'的属性,因此我们不仅有了获取和设置该名称的语法方法,而且这样做对我们来说是有意义的。”
再一次,从一个稍微不同和更一般的角度来解决这个问题,但我希望这有助于Person类的下一个实例找到这个线程的方法。
推荐文章
- 一行if语句不工作
- 在Ruby中将整数转换为十六进制字符串
- 如何记录Ruby代码?
- Ruby:包含的反义词是什么?Ruby数组?
- 在Ruby中,proc和lambda有什么区别?
- 如何传递参数到一个Rake任务与环境在Rails?
- 获取当前正在执行的方法的名称
- 如何在Rails中计算相对时间?
- 在Ruby中使用范围填充数组的正确方法
- “for”和“each”在Ruby中
- 我如何复制一个哈希在Ruby?
- Ruby/Rails:将Date转换为UNIX时间戳
- 我如何编码/解码HTML实体在Ruby?
- Ruby有一个string. startwith ("abc")内置方法吗?
- 如何从URL下载文件并保存在Rails中?