在Ruby中,self代表預設的訊息接收者,不同的範圍或呼叫方式,self代表的物件也不相同。在頂層環境中,self是參考至一個名稱為main的物件,為Object的實例:
>> self.is_a? Object
=> true
>> self
=> main
>> self.instance_of? Object
=> true
>>
=> true
>> self
=> main
>> self.instance_of? Object
=> true
>>
在頂層環境中定義方法,相當於在Object類別中定義私有實例方法。例如:
def some
puts "Some"
end
puts "Some"
end
相當於如下定義:
class Object
def some
puts "Some"
end
private :some
end
def some
puts "Some"
end
private :some
end
在Ruby中呼叫方法時沒有指定訊息接收者,那麼預設的訊息接收者就是self,在頂層環境時,self代表Object實例,也因此在頂層環境中定義的方法,可以在類別、方法之中直接呼叫。
不過Ruby中,private方法不需也不能透過self呼叫。例如:
>> def some
>> puts "some"
>> end
=> nil
>> some
some
=> nil
>> self.some
NoMethodError: private method `some' called for main:Object
from (irb):13
from C:/Winware/Ruby192/bin/irb:12:in `<main>'
>>
>> puts "some"
>> end
=> nil
>> some
some
=> nil
>> self.some
NoMethodError: private method `some' called for main:Object
from (irb):13
from C:/Winware/Ruby192/bin/irb:12:in `<main>'
>>
private方法不需也不能透過self呼叫的唯一例外,是在類別中的方法呼叫指定方法時。例如:
>> class Some
>> def initialize(value)
>> self.value = value
>> end
>> def value=(v)
>> @value = v
>> end
>> private :value=
>> def value
>> @value
>> end
>> end
=> nil
>> s = Some.new(10)
=> #<Some:0x26eb168 @value=10>
>> s.value
=> 10
>>
>> def initialize(value)
>> self.value = value
>> end
>> def value=(v)
>> @value = v
>> end
>> private :value=
>> def value
>> @value
>> end
>> end
=> nil
>> s = Some.new(10)
=> #<Some:0x26eb168 @value=10>
>> s.value
=> 10
>>
在上例的initialize方法中,想呼叫private的value方法將值指定給實例變數@value,由於Ruby中若發現=指定,會將值指定給區域變數,為了區別,這種情況下必須使用self明確指定,是要呼叫value()方法,而不是設定區域變數,如果沒有指定self,就會如下:
>> class Some
>> def initialize(value)
>> value = value
>> end
>> def value=(v)
>> @value = v
>> end
>> private :value=
>> def value
>> @value
>> end
>> end
=> nil
>> s = Some.new(10)
=> #<Some:0x512208>
>> s.value
=> nil
>>
>> def initialize(value)
>> value = value
>> end
>> def value=(v)
>> @value = v
>> end
>> private :value=
>> def value
>> @value
>> end
>> end
=> nil
>> s = Some.new(10)
=> #<Some:0x512208>
>> s.value
=> nil
>>
在單例方法或實例方法中,self代表呼叫方法時逗號左邊的物件。例如:
>> obj = Object.new
=> #<Object:0x25f6c80>
>> def obj.self_id
>> self.object_id
>> end
=> nil
>> obj.object_id
=> 19904064
>> obj.self_id
=> 19904064
>> class Some
>> def self_id
>> self.object_id
>> end
>> end
=> nil
>> s = Some.new
=> #<Some:0x276e520>
>> s.object_id
=> 20673168
>> s.self_id
=> 20673168
>>
=> #<Object:0x25f6c80>
>> def obj.self_id
>> self.object_id
>> end
=> nil
>> obj.object_id
=> 19904064
>> obj.self_id
=> 19904064
>> class Some
>> def self_id
>> self.object_id
>> end
>> end
=> nil
>> s = Some.new
=> #<Some:0x276e520>
>> s.object_id
=> 20673168
>> s.self_id
=> 20673168
>>
在類別本體中,self代表類別本身(也就是Class實例)。例如:
>> class Some
>> puts self.object_id
>> end
19600008
=> nil
>> Some.object_id
=> 19600008
>>
>> puts self.object_id
>> end
19600008
=> nil
>> Some.object_id
=> 19600008
>>
所以,在定義類別方法時,可以使用self代替具體的類別名稱。例如:
class Some
def Some.action
puts "Some.action"
end
end
def Some.action
puts "Some.action"
end
end
可以改用以下的寫法,如此以後修改類別名稱,就不用特別再修改類別方法前的名稱:
class Some
def self.action
puts "Some.action"
end
end
def self.action
puts "Some.action"
end
end
在 單例方法、實例方法、類別方法 中談過,類別方法實際上是類別的單例方法,所以在類別方法中,self就是代表類別。例如:
>> class Some
>> def self.self_id
>> self.object_id
>> end
>> end
=> nil
>> Some.object_id
=> 18863088
>> Some.self_id
=> 18863088
>>
>> def self.self_id
>> self.object_id
>> end
>> end
=> nil
>> Some.object_id
=> 18863088
>> Some.self_id
=> 18863088
>>