我希望有人能解釋為什么我從這兩種方法中得到相同的行為,以及何時使用或不使用 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。謝謝你。
uj5u.com熱心網友回復:
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
uj5u.com熱心網友回復:
我會回答你的問題,但這不會幫助你理解在self.定義方法時何時使用前綴。因此,我需要先介紹一些有關實體方法的背景資訊。
假設我們有以下類定義。
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、一個類方法C::c和一個實體方法。Cs
請注意,由于self #=> C在課堂上,寫作def self.c ...與def C.c .... 寫作的唯一原因self是,如果我們重命名課程,我們不必更改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只是告訴 Ruby 您希望在的單例類上創建實體方法的一種簡寫方式。 同樣,對“類方法”的參考是那些相同實體方法的簡寫。事實上,沒有必要定義帶有前綴的方法。您可以改用and ,就像我所做的那樣,或者選擇其他幾種方式中的一種,最常見的是sCself.singleton_classdefine_method
class C
class << self
def s
puts "self in s = #{self}"
"s"
end
end
end
whereclass << 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
請注意,如果將其設為公共方法,它將可供所有物件使用,這顯然會導致災難。
接下來考慮:
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's ( main's) 單例類上定義,我們可以確認:
self.singleton_class.instance_methods.include?(:your_instance_method)
#=> true
因此,隱式接收者
your_instance_method
是self, 等于main, 給出相同的結果
self.send(:your_instance_method)
這是一個復雜的主題(關于 Ruby 的Object Model),特別是對于 Ruby 的新手來說,所以如果您不能完全按照我所說的進行操作,請不要擔心。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/460553.html
上一篇:Ruby,如何獲取同一方法中方法的整個命名空間定義路徑?
下一篇:匹配和包括?方法
