ruby - Ruby 中的实例变量;为什么我必须(有时)指定`self`?
问题描述
为什么 increment_v1 和_v3 工作,但 increment_v2 和 _v4 不工作(v2 返回正确的值,但不改变@counter
,v4 失败,“NoMethodError(未定义的方法 `+' for nil:NilClass)”)
class MyClass
attr_accessor :counter
def initialize
@counter = 0
end
def increment_v1
@counter = counter + 1
end
def increment_v2
counter = @counter + 1
end
def increment_v3
@counter += 1
end
def increment_v4
counter += 1
end
end
我希望所有这些方法都有相同的结果(增加@counter
值并返回增加的数字)。如果我attr_accessor
用attr_reader
and替换它有同样的错误attr_writer
。我觉得我可能对这些attr_*
方法有误解。
这是它在控制台中的样子:
2.6.3 :026 > a = MyClass.new
=> #<MyClass:0x00000000018d7240 @counter=0>
2.6.3 :027 > a.increment_v1
=> 1
2.6.3 :028 > a
=> #<MyClass:0x00000000018d7240 @counter=1>
2.6.3 :029 > a.increment_v2
=> 2
2.6.3 :030 > a
=> #<MyClass:0x00000000018d7240 @counter=1>
2.6.3 :031 > a.increment_v3
=> 2
2.6.3 :032 > a
=> #<MyClass:0x00000000018d7240 @counter=2>
2.6.3 :033 > a.increment_v4
Traceback (most recent call last):
5: from /home/guin/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `<main>'
4: from /home/guin/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `load'
3: from /home/guin/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
2: from (irb):33
1: from (irb):23:in `increment_v4'
NoMethodError (undefined method `+' for nil:NilClass)
a.counter += 1
从课外跑步按我的预期工作。self.counter += 1
当我在课堂上时,我必须指定吗?为什么?它甚至可以与self.counter = counter + 1
. 到底是怎么回事?
解决方案
正如您所展示的,您始终可以使用实例变量 ( @counter
) 直接访问属性。但是,您的问题与生成的 getter/setter 方法有关attr_accessor
。
除非您有同名的局部变量,否则getter 方法不需要 self 。设置方法是不同的。您总是需要将 self 与 setter 一起使用。
例如:
def test_method
# directly set instance var. this will always work
@counter = 1
# define local variable with same name.
# this does not call the setter because you don't use self
counter = 0
puts counter
# prints 0
# The getter method is never called because you have a local variable
# with the same name.
puts self.counter
# prints 1
# you can force the getter to be called by using self
end
我认为编写方法的惯用方式是:
def increment_v5
self.counter += 1
end
但是你也可以这样写:
def increment_v6
self.counter = counter + 1
# \ calls getter
end
还有很多其他的写法。
推荐阅读
- ibm-cloud - 如何修复 Inside Node-Red IbmIot Node 不将 Bluemix 显示为身份验证选项?
- android - 为什么使用 YouTube 数据 API 中的“搜索”功能会占用我这么多的配额?
- sql - SQL Select Query 搜索多个列并在合并列中返回结果
- batch-file - 带有 .csv 输出的常量 ping 批处理文件无法正常工作
- raku - 终端 ANSI 颜色不适用于 Inline::Perl5 (Data::Printer)
- django - 使用 django 创建指向在我的数据库中显示特定行的页面的链接?
- css - 如何基于flexbox创建网格系统?
- react-native - 如何在控制台中获取 React Native 运行时的全局变量?
- c# - EF:不带条件的选择更新
- react-native - 我正在尝试使用 react-native-html-parser 来感染 html 页面