我很难理解Ruby中的attr_accessor。 有人能给我解释一下吗?
当前回答
它只是一个为实例变量定义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类的下一个实例找到这个线程的方法。
另一种理解它的方法是通过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
如果你熟悉面向对象的概念,你必须熟悉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"
假设您有一个类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文档。
我是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
推荐文章
- 是否可以在MiniTest中运行单个测试?
- 如何在Ruby中生成a和b之间的随机数?
- 无法安装gem -未能建立gem本地扩展-无法加载这样的文件——mkmf (LoadError)
- 如何在Ruby中创建文件
- 什么是Ruby文件。开放模式和选项?
- Ruby数组到字符串的转换
- 如何分割(块)一个Ruby数组成X元素的部分?
- Ruby中“or”和||的区别?
- 如何测试参数是否存在在轨道
- 在Ruby中不创建新字符串而修饰字符串的规范方法是什么?
- RVM不是一个函数,用' RVM use…’不会起作用
- 了解Gemfile。锁文件
- 如何确定一个数组是否包含另一个数组的所有元素
- 是什么导致这个ActiveRecord::ReadOnlyRecord错误?
- 最好的打印散列的方法