在 ruby 中引用 class 实例变量时理解 self 关键字?
Understanding the self keyword when referring to a class instance variable in a ruby?
我正在尝试理解 ruby 对象和 self 关键字。
假设我有一个 class:
class CashRegister
attr_accessor :total
def initialize(total)
@total = total
end
def add(amount)
self.total = self.total + amount
end
end
cr = CashRegister.new(5)
puts cr.total #=> 5
cr.add(10)
puts cr.total #=> 15
假设我在上面的添加方法中删除了 self 关键字:
def add(amount)
total = total + amount
end
我得到一个错误:
cr = CashRegister.new(5)
puts cr.total #=> 5
cr.add(10) #=> this throws an error: ./lib/test.rb:28:in `add': undefined method `+' for nil:NilClass (NoMethodError)
我假设这是因为我需要 self 关键字来引用实例变量 total
假设我有另一个类似的 class:
class School
attr_accessor :name, :roster
def initialize(name)
@name = name
@roster = {}
end
def add_student(student, grade)
roster[grade] = roster[grade] || []
roster[grade] << student
end
end
school = School.new("Jefferson High")
puts school.roster #=> {}
school.add_student("Sam", 10)
puts school.roster #=> {10=>["Sam"]}
为什么我在 add_student 中不需要自己?
tl;dr:foo = value
将始终引用局部变量 foo
而不是方法调用 self.foo=(value)
.
I am assumed this is because I need the self keyword to refer to the instance variable, total
不是,total
是局部变量,不是实例变量。 @total
是一个实例变量。局部变量存在于当前范围内,就像单个方法调用一样。实例变量与对象保持一致。
您需要 self
关键字来引用方法 total=
。让我们开始吧。
attr_accessor :total
声明了两个方法,total
和 total=
。这些是获取和设置实例变量 @total
的包装器。以下代码执行等效操作。
def total
@total
end
def total=(value)
@total = value
end
注意这个方法的名字是total=
,这个稍后会变得很重要。
考虑到这一点,让我们看看您的代码。
def add(amount)
self.total = self.total + amount
end
(几乎)Ruby 中的所有内容实际上都是方法调用。以上是在 self
.
上调用 total=
方法的语法糖
def add(amount)
self.total=(self.total + amount)
end
现在如果我们像这样删除 self
会发生什么?
def add(amount)
total = total + amount
end
在Ruby中,self
是可选的。 Ruby 会判断 total
是指方法 total
还是局部变量 total
。 局部变量优先并且赋值总是给局部变量.
total = total + amount
像这样工作:
def add(amount)
total = self.total + amount
end
始终赋值给局部变量。
为了进一步说明,如果我们先声明 total
会怎样?
def add(amount)
total = 23
self.total = total + amount
end
现有局部变量 total
优先于 total()
方法。 total + amount
指的是局部变量 total
所以 cr.add(10); puts cr.total
将是 33.
total = ...
将始终引用局部变量 total
。出于这个原因,如果你想使用方法赋值,你必须显式地使用 self.total=
。在其他情况下,您可以删除 self
。并避免与方法同名的局部变量。
def add(amount)
# self.total = self.total + amount
self.total = total + amount
end
Why did I not need self in add_student?
因为没有歧义。您没有分配给局部变量 roster
.
def add_student(student, grade)
roster[grade] = roster[grade] || []
roster[grade] << student
end
roster[grade]
真的是self.roster.[]=(grade)
。您正在调用 self.roster
which returns a Hash
然后调用该哈希上的 []=
方法来给它一个新的 key/value 对。
类似地,roster[grade] << student
是self.roster.[](grade).<<(student). Get a
Hash, call [
[]](https://ruby-doc.org/core/Hash.html#method-i-5B-5D) on it to retrieve the
Arrayand call [
<<](https://ruby-doc.org/core/Array.html#method-i-3C-3C) on that
Array`.
def add_student(student, grade)
self.roster.[]=(grade) = self.roster.[](grade) || []
self.roster.[](grade).<<(student)
end
是的,[]
、[]=
和 <<
都是方法名称。
一旦理解语法糖下的方法调用以及 []
、[]=
、<<
等内容,许多 Ruby 的谜团就会消失是方法名称。
我正在尝试理解 ruby 对象和 self 关键字。
假设我有一个 class:
class CashRegister
attr_accessor :total
def initialize(total)
@total = total
end
def add(amount)
self.total = self.total + amount
end
end
cr = CashRegister.new(5)
puts cr.total #=> 5
cr.add(10)
puts cr.total #=> 15
假设我在上面的添加方法中删除了 self 关键字:
def add(amount)
total = total + amount
end
我得到一个错误:
cr = CashRegister.new(5)
puts cr.total #=> 5
cr.add(10) #=> this throws an error: ./lib/test.rb:28:in `add': undefined method `+' for nil:NilClass (NoMethodError)
我假设这是因为我需要 self 关键字来引用实例变量 total
假设我有另一个类似的 class:
class School
attr_accessor :name, :roster
def initialize(name)
@name = name
@roster = {}
end
def add_student(student, grade)
roster[grade] = roster[grade] || []
roster[grade] << student
end
end
school = School.new("Jefferson High")
puts school.roster #=> {}
school.add_student("Sam", 10)
puts school.roster #=> {10=>["Sam"]}
为什么我在 add_student 中不需要自己?
tl;dr:foo = value
将始终引用局部变量 foo
而不是方法调用 self.foo=(value)
.
I am assumed this is because I need the self keyword to refer to the instance variable, total
不是,total
是局部变量,不是实例变量。 @total
是一个实例变量。局部变量存在于当前范围内,就像单个方法调用一样。实例变量与对象保持一致。
您需要 self
关键字来引用方法 total=
。让我们开始吧。
attr_accessor :total
声明了两个方法,total
和 total=
。这些是获取和设置实例变量 @total
的包装器。以下代码执行等效操作。
def total
@total
end
def total=(value)
@total = value
end
注意这个方法的名字是total=
,这个稍后会变得很重要。
考虑到这一点,让我们看看您的代码。
def add(amount)
self.total = self.total + amount
end
(几乎)Ruby 中的所有内容实际上都是方法调用。以上是在 self
.
total=
方法的语法糖
def add(amount)
self.total=(self.total + amount)
end
现在如果我们像这样删除 self
会发生什么?
def add(amount)
total = total + amount
end
在Ruby中,self
是可选的。 Ruby 会判断 total
是指方法 total
还是局部变量 total
。 局部变量优先并且赋值总是给局部变量.
total = total + amount
像这样工作:
def add(amount)
total = self.total + amount
end
始终赋值给局部变量。
为了进一步说明,如果我们先声明 total
会怎样?
def add(amount)
total = 23
self.total = total + amount
end
现有局部变量 total
优先于 total()
方法。 total + amount
指的是局部变量 total
所以 cr.add(10); puts cr.total
将是 33.
total = ...
将始终引用局部变量 total
。出于这个原因,如果你想使用方法赋值,你必须显式地使用 self.total=
。在其他情况下,您可以删除 self
。并避免与方法同名的局部变量。
def add(amount)
# self.total = self.total + amount
self.total = total + amount
end
Why did I not need self in add_student?
因为没有歧义。您没有分配给局部变量 roster
.
def add_student(student, grade)
roster[grade] = roster[grade] || []
roster[grade] << student
end
roster[grade]
真的是self.roster.[]=(grade)
。您正在调用 self.roster
which returns a Hash
然后调用该哈希上的 []=
方法来给它一个新的 key/value 对。
类似地,roster[grade] << student
是self.roster.[](grade).<<(student). Get a
Hash, call [
[]](https://ruby-doc.org/core/Hash.html#method-i-5B-5D) on it to retrieve the
Arrayand call [
<<](https://ruby-doc.org/core/Array.html#method-i-3C-3C) on that
Array`.
def add_student(student, grade)
self.roster.[]=(grade) = self.roster.[](grade) || []
self.roster.[](grade).<<(student)
end
是的,[]
、[]=
和 <<
都是方法名称。
一旦理解语法糖下的方法调用以及 []
、[]=
、<<
等内容,许多 Ruby 的谜团就会消失是方法名称。