我什么时候需要单独使用 self.instance_method 与 instance_method?
When do I need to use self.instance_method vs instance_method alone?
我希望有人能解释为什么我从这两种方法中获得相同的行为,以及何时使用或不使用 self 意味着什么。
def my_instance_method(arg)
'execute some code' if another_instance_method_of_same_class?(arg)
end
似乎与
的行为完全相同
def my_instance_method(arg)
'execute some code' if self.another_instance_method_of_same_class?(arg)
end
如果我的搜索技巧没有达到标准,我深表歉意,但我找不到这个问题的确切答案,只是解释了 self 做了什么(这让我觉得我应该需要它)。
我正在使用 Ruby 的最新版本。谢谢。
self.foo(...)
和 foo(...)
之间存在一些差异,但它们基本相同。
隐私
private
方法只能通过 foo
直接调用,而不能使用显式接收者。因此,如果 foo
被标记为 private
,那么您 必须 调用它而无需 self
。
class Example
private def foo(x)
x + 1
end
def bar
foo # Works fine
self.foo # Error: foo is private
end
end
阴影
如果您在当前函数中有一个名为 foo
的局部变量,那么在不带参数的情况下编写 foo
将改为引用局部变量
class Example
def foo(*args)
puts "Hello :)"
end
def bar
foo = 100 # Just an ordinary variable; no relation to the above method
foo # This refers to the local variable called "foo"
self.foo # This calls the method foo() with no arguments
foo(1) # This calls the method foo() with one argument
self.foo(1) # Equivalent to the above; calls with one argument
end
def baz
foo # There's no local variable called "foo", so this calls the method
end
end
作业
如果您谈论的方法是赋值方法(即以 =
结尾),则必须始终使用显式接收者调用它
class Example
def foo=(value)
puts "Assigning foo = #{value}"
end
def bar
foo = 0 # This creates a new local variable called foo and assigns to it
self.foo = 0 # Calls foo= on self
end
end
我会回答你的问题,但这并不能帮助你理解在定义方法时什么时候要使用前缀self.
。因此,我需要首先介绍一些关于 实例方法 .
的背景信息
假设我们有以下 class 定义。
class C
puts "self = #{self}
def i
puts "self in i = #{self}"
"i"
end
def self.c
puts "self in c = #{self}"
"c"
end
singleton_class.define_method(:s) do
puts "self in s = #{self}"
"s"
end
end
#=> :s
self = C
我定义了一个实例方法 C#i
、一个 class 方法 C::c
和一个实例方法 C
单例 class、s
.
请注意,由于self #=> C
在class中,因此写def self.c ...
与def C.c ...
完全相同。写 self
的唯一原因是如果我们重命名 class 我们不必更改 def self.c ...
和
“self”比“PhilharmonicOrchestras”更难拼错。
不出所料,
C.instance_methods(false)
#=> [:i]
instance = C.new
#=> #<C:0x00007ff0011074f0>
instance.i
#=> "i"
self in i = #<C:0x00007ff0011074f0>
现在考虑最后两种方法:
C.methods(false)
#=> [:s, :c]
C.c
#=> "c"
self in c = C
C.singleton_class.instance_methods(false)
#=> [:s, :c]
C.s
#=> "s"
self in s = C
这表明定义方法 def self.class.c
只是一种 shorthand 告诉 Ruby 您希望创建 实例方法 的方式s
在 C
的单身人士 class 上。同样,对于那些相同的实例方法,对“class 方法”的引用是 shorthand。其实不需要定义前缀为self.
的方法。您可以像我所做的那样使用 singleton_class
和 define_method
,或者选择其他几种方式之一,最常见的是
class C
class << self
def s
puts "self in s = #{self}"
"s"
end
end
end
其中 class << self .. end
导致 self
从 C
变为 C.singleton_class
。
你定义了一个方法,我会稍微修改一下:
self
#=> main
def my_instance_method
puts "self = #{self}, self.class = #{self.class}"
'execute some code'
end
my_instance_method
#=> "execute some code"
self = main, self.class = Object
由于所有方法都是实例方法,所以这也必须是一个,即 Object
:
的私有实例方法
Object.private_instance_methods.include?(:my_instance_method)
#=> true
作为私有实例方法,我们不能在作为 Object
(main
) 实例的显式接收器上调用它,但我们可以这样写:
Object.new.send(:my_instance_method)
#=> "execute some code"
self = #<Object:0x00007f988514e180>, self.class = Object
请注意,如果它是一个 public 方法,它将可供所有对象使用,这显然会导致灾难。
接下来考虑:
def self.your_instance_method
puts "self = #{self}, self.class = #{self.class}"
'execute some code'
end
your_instance_method
#=> "execute some code"
self = main, self.class = Object
这个方法必须定义在self
的(main
的)单例class上,我们可以确认:
self.singleton_class.instance_methods.include?(:your_instance_method)
#=> true
因此,
的隐含接收者
your_instance_method
是 self
,等于 main
,结果与
相同
self.send(:your_instance_method)
这是一个复杂的主题(关于 Ruby 的 Object Model),特别是对于 Ruby 的新手来说,所以如果您无法理解,请不要担心按照我说的做。
我希望有人能解释为什么我从这两种方法中获得相同的行为,以及何时使用或不使用 self 意味着什么。
def my_instance_method(arg)
'execute some code' if another_instance_method_of_same_class?(arg)
end
似乎与
的行为完全相同def my_instance_method(arg)
'execute some code' if self.another_instance_method_of_same_class?(arg)
end
如果我的搜索技巧没有达到标准,我深表歉意,但我找不到这个问题的确切答案,只是解释了 self 做了什么(这让我觉得我应该需要它)。 我正在使用 Ruby 的最新版本。谢谢。
self.foo(...)
和 foo(...)
之间存在一些差异,但它们基本相同。
隐私
private
方法只能通过 foo
直接调用,而不能使用显式接收者。因此,如果 foo
被标记为 private
,那么您 必须 调用它而无需 self
。
class Example
private def foo(x)
x + 1
end
def bar
foo # Works fine
self.foo # Error: foo is private
end
end
阴影
如果您在当前函数中有一个名为 foo
的局部变量,那么在不带参数的情况下编写 foo
将改为引用局部变量
class Example
def foo(*args)
puts "Hello :)"
end
def bar
foo = 100 # Just an ordinary variable; no relation to the above method
foo # This refers to the local variable called "foo"
self.foo # This calls the method foo() with no arguments
foo(1) # This calls the method foo() with one argument
self.foo(1) # Equivalent to the above; calls with one argument
end
def baz
foo # There's no local variable called "foo", so this calls the method
end
end
作业
如果您谈论的方法是赋值方法(即以 =
结尾),则必须始终使用显式接收者调用它
class Example
def foo=(value)
puts "Assigning foo = #{value}"
end
def bar
foo = 0 # This creates a new local variable called foo and assigns to it
self.foo = 0 # Calls foo= on self
end
end
我会回答你的问题,但这并不能帮助你理解在定义方法时什么时候要使用前缀self.
。因此,我需要首先介绍一些关于 实例方法 .
假设我们有以下 class 定义。
class C
puts "self = #{self}
def i
puts "self in i = #{self}"
"i"
end
def self.c
puts "self in c = #{self}"
"c"
end
singleton_class.define_method(:s) do
puts "self in s = #{self}"
"s"
end
end
#=> :s
self = C
我定义了一个实例方法 C#i
、一个 class 方法 C::c
和一个实例方法 C
单例 class、s
.
请注意,由于self #=> C
在class中,因此写def self.c ...
与def C.c ...
完全相同。写 self
的唯一原因是如果我们重命名 class 我们不必更改 def self.c ...
和
“self”比“PhilharmonicOrchestras”更难拼错。
不出所料,
C.instance_methods(false)
#=> [:i]
instance = C.new
#=> #<C:0x00007ff0011074f0>
instance.i
#=> "i"
self in i = #<C:0x00007ff0011074f0>
现在考虑最后两种方法:
C.methods(false)
#=> [:s, :c]
C.c
#=> "c"
self in c = C
C.singleton_class.instance_methods(false)
#=> [:s, :c]
C.s
#=> "s"
self in s = C
这表明定义方法 def self.class.c
只是一种 shorthand 告诉 Ruby 您希望创建 实例方法 的方式s
在 C
的单身人士 class 上。同样,对于那些相同的实例方法,对“class 方法”的引用是 shorthand。其实不需要定义前缀为self.
的方法。您可以像我所做的那样使用 singleton_class
和 define_method
,或者选择其他几种方式之一,最常见的是
class C
class << self
def s
puts "self in s = #{self}"
"s"
end
end
end
其中 class << self .. end
导致 self
从 C
变为 C.singleton_class
。
你定义了一个方法,我会稍微修改一下:
self
#=> main
def my_instance_method
puts "self = #{self}, self.class = #{self.class}"
'execute some code'
end
my_instance_method
#=> "execute some code"
self = main, self.class = Object
由于所有方法都是实例方法,所以这也必须是一个,即 Object
:
Object.private_instance_methods.include?(:my_instance_method)
#=> true
作为私有实例方法,我们不能在作为 Object
(main
) 实例的显式接收器上调用它,但我们可以这样写:
Object.new.send(:my_instance_method)
#=> "execute some code"
self = #<Object:0x00007f988514e180>, self.class = Object
请注意,如果它是一个 public 方法,它将可供所有对象使用,这显然会导致灾难。
接下来考虑:
def self.your_instance_method
puts "self = #{self}, self.class = #{self.class}"
'execute some code'
end
your_instance_method
#=> "execute some code"
self = main, self.class = Object
这个方法必须定义在self
的(main
的)单例class上,我们可以确认:
self.singleton_class.instance_methods.include?(:your_instance_method)
#=> true
因此,
的隐含接收者your_instance_method
是 self
,等于 main
,结果与
self.send(:your_instance_method)
这是一个复杂的主题(关于 Ruby 的 Object Model),特别是对于 Ruby 的新手来说,所以如果您无法理解,请不要担心按照我说的做。