了解在 Ruby 中初始化时分配的变量的访问
Understanding the access of a variable assigned in initialize in Ruby
作为初学者,我不太了解 self
所以我很难理解 self.blogs
是如何初始化的,blogs
然后是 self.blogs
在 add_blog
方法之后的下一行,都在下面的代码中一起工作。
为什么add_blog
方法中的blogs
和initalize中的self.blogs
访问同一个变量?
那为什么后面用self.blogs
对blogs
数组排序呢?
此外,如果我在初始化中使用 @blogs
而不是 self.blogs
会有影响吗?
class User
attr_accessor :username, :blogs
def initialize(username)
self.username = username
self.blogs = []
end
def add_blog(date, text)
added_blog = Blog.new(date, self, text)
blogs << added_blog
self.blogs = blogs.sort_by { |blog| blog.date }.reverse
added_blog
end
end
@variable
将直接访问 class 的实例变量。写入 self.variable
将向对象发送一条消息 variable
。默认情况下,它将 return 实例变量,但它可以根据您设置对象的方式做其他事情。它可以是对方法的调用,或子class,或其他任何东西。
调用blogs
或self.blogs
的区别完全取决于语法。如果你使用像 rubocop 这样的自以为是的语法检查器,它会告诉你你有多余的使用 self
对于大多数对自身的方法调用,self.method_name
等同于 method_name
。但是,名称以 =
结尾的方法并非如此。
首先要注意的是,self.blogs = etc
不会调用名为 blogs
的方法,然后以某种方式调用 'assign etc to it';该行调用方法 blogs=
,并将 etc
作为参数传递给它。
您不能像使用其他方法调用那样将其缩短为 blogs = etc
的原因是因为 blogs = etc
与创建名为 blogs
的新局部变量没有区别.
在上一行中,当您看到一个裸露的 blogs
时,即 也是一个方法调用 ,并且可以很容易地写成 self.blogs
.用隐式接收器编写它只是更短。当然,blogs
作为局部变量的使用也可能存在歧义,但在这种情况下,解析器可以判断它不是,因为先前在方法中没有分配名为 blogs
的局部变量(如果曾经有一个裸露的 blogs
将具有该局部变量的值,如果您的意思是方法调用,则 self.blogs
是必需的。
至于使用@blogs =
而不是self.blogs =
,在这种情况下它会产生相同的效果,但是是一个细微的区别:如果你稍后重新定义 blogs=
方法以获得其他效果(例如,将消息写入日志),对 self.blogs =
的调用将获取这些更改,而直接访问则不会。在极端情况下,如果您重新定义 blogs=
以将值存储在数据库中而不是实例变量中,@blogs =
甚至不会再 similar (尽管显然,基础设施的这种重大变化可能会在 class 内部产生连锁反应,无论如何)。
为了回答你的问题,我们必须揭示 attr_accessor
的真实本质。
class Foo
attr_accessor :bar
end
完全等同于
class Foo
def bar
@bar
end
def bar=(value)
@bar = value
end
end
可以看到attr_accessor :bar
定义了两个实例方法Foo#bar
和Foo#bar=
访问一个实例变量@bar
.
然后让我们看看您的代码。
initialize
中的self.blogs = []
实际上是调用方法User#blogs=
,并通过它设置实例变量@blogs
为空数组。可以写成 self.blogs=([])
但是很吵,不是吗?顺便说一句,你不能在这里省略 self.
否则它只是设置一个局部变量。
blogs << added_blog
调用 User#blog
方法 returns @blogs
的值。它也可以写成 self.blogs().push(added_blog)
,但又不是 rubyish。可以省略self.
因为User#add_blog
中没有名为blogs
的局部变量,所以ruby回退调用实例方法.
self.blogs = blogs.sort_by { |blog| blog.date }.reverse
混合调用 User#blogs=
和 User#blogs
.
作为初学者,我不太了解 self
所以我很难理解 self.blogs
是如何初始化的,blogs
然后是 self.blogs
在 add_blog
方法之后的下一行,都在下面的代码中一起工作。
为什么add_blog
方法中的blogs
和initalize中的self.blogs
访问同一个变量?
那为什么后面用self.blogs
对blogs
数组排序呢?
此外,如果我在初始化中使用 @blogs
而不是 self.blogs
会有影响吗?
class User
attr_accessor :username, :blogs
def initialize(username)
self.username = username
self.blogs = []
end
def add_blog(date, text)
added_blog = Blog.new(date, self, text)
blogs << added_blog
self.blogs = blogs.sort_by { |blog| blog.date }.reverse
added_blog
end
end
@variable
将直接访问 class 的实例变量。写入 self.variable
将向对象发送一条消息 variable
。默认情况下,它将 return 实例变量,但它可以根据您设置对象的方式做其他事情。它可以是对方法的调用,或子class,或其他任何东西。
调用blogs
或self.blogs
的区别完全取决于语法。如果你使用像 rubocop 这样的自以为是的语法检查器,它会告诉你你有多余的使用 self
对于大多数对自身的方法调用,self.method_name
等同于 method_name
。但是,名称以 =
结尾的方法并非如此。
首先要注意的是,self.blogs = etc
不会调用名为 blogs
的方法,然后以某种方式调用 'assign etc to it';该行调用方法 blogs=
,并将 etc
作为参数传递给它。
您不能像使用其他方法调用那样将其缩短为 blogs = etc
的原因是因为 blogs = etc
与创建名为 blogs
的新局部变量没有区别.
在上一行中,当您看到一个裸露的 blogs
时,即 也是一个方法调用 ,并且可以很容易地写成 self.blogs
.用隐式接收器编写它只是更短。当然,blogs
作为局部变量的使用也可能存在歧义,但在这种情况下,解析器可以判断它不是,因为先前在方法中没有分配名为 blogs
的局部变量(如果曾经有一个裸露的 blogs
将具有该局部变量的值,如果您的意思是方法调用,则 self.blogs
是必需的。
至于使用@blogs =
而不是self.blogs =
,在这种情况下它会产生相同的效果,但是是一个细微的区别:如果你稍后重新定义 blogs=
方法以获得其他效果(例如,将消息写入日志),对 self.blogs =
的调用将获取这些更改,而直接访问则不会。在极端情况下,如果您重新定义 blogs=
以将值存储在数据库中而不是实例变量中,@blogs =
甚至不会再 similar (尽管显然,基础设施的这种重大变化可能会在 class 内部产生连锁反应,无论如何)。
为了回答你的问题,我们必须揭示 attr_accessor
的真实本质。
class Foo
attr_accessor :bar
end
完全等同于
class Foo
def bar
@bar
end
def bar=(value)
@bar = value
end
end
可以看到attr_accessor :bar
定义了两个实例方法Foo#bar
和Foo#bar=
访问一个实例变量@bar
.
然后让我们看看您的代码。
initialize
中的self.blogs = []
实际上是调用方法User#blogs=
,并通过它设置实例变量@blogs
为空数组。可以写成 self.blogs=([])
但是很吵,不是吗?顺便说一句,你不能在这里省略 self.
否则它只是设置一个局部变量。
blogs << added_blog
调用 User#blog
方法 returns @blogs
的值。它也可以写成 self.blogs().push(added_blog)
,但又不是 rubyish。可以省略self.
因为User#add_blog
中没有名为blogs
的局部变量,所以ruby回退调用实例方法.
self.blogs = blogs.sort_by { |blog| blog.date }.reverse
混合调用 User#blogs=
和 User#blogs
.