2011-07-12 45 views

回答

8

關於Python,我可以告訴你沒有什麼新東西。正如pst所說,self作爲一種方法的第一個參數通常被傳遞。從Python docs

通常,方法的第一個參數稱爲self。這只不過是一個約定:名字self對Python來說絕對沒有特殊含義。但是,請注意,通過不遵循約定,您的代碼對其他Python程序員而言可能會不易讀取,並且可以想象,可能會編寫一個依賴於這種約定的類瀏覽器程序。

CRuby(或'MRI')有一些類似的情況發生在引擎蓋下。每個C延伸部可以限定(模塊/類/單)上的Ruby類的方法,通過使用

  • rb_define_method(實例)
  • rb_define_singleton_method(singleton類)
  • rb_define_module_function(類/模塊)

實際的實現函數總是以VALUE self作爲它們的第一個參數,類比於Python成語。 self在這些情況下指的是這個特殊的郵件已經發送到對象實例,也就是說,如果你有

person = Person.new 
person.do_sth 

和do_sth會發生在C中實現,那麼將有一個對應的C函數

VALUE 
person_do_sth(VALUE self) { 
    //do something 
    return self; 
} 

每個這樣的實施具有返回,其涉及這樣的事實,每個方法調用或消息中發送(粘到Smalltalk的說法)一個VALUE(Ruby對象的C-表示)中具有返回值紅寶石。 Ruby中沒有這樣的東西,例如void函數。

儘管我們需要在低級C代碼中來回傳遞self,但您不需要在Ruby代碼中這樣做,Ruby會爲您處理此問題。 self的當前值存儲在內部執行的當前線程上下文中,因此self的存在被授予,消息「self」將始終評估爲某個對象。

由於Ruby的動態特性,被self引用的該對象的實際值隨當前解釋的代碼的當前範圍而變化。運行此看到自己:

puts "#{self} - declared in global scope" # the 'top self' aka 'main' 
class << self 
    puts "#{self} - 'main's singleton class" # main's singleton or 'eigenclass' 
end 

puts "Starting to interpret class A code" 

class A 
    puts "#{self} - When do I get executed!?" # self is class A 

    class << self 
    puts "#{self} - And me!?" # now A's singleton class 
    def a # declaring method in class's singleton class results in class method 
     puts "#{self} - declared in singleton class" # it's A 
    end 
    end 

    def self.b 
    puts "#{self} - declared in class method" # self is class A again -> class method 
    class << self 
     puts "#{self} - declared in Class A's singleton class" # now it's Class A's singleton class 
    end 
    end 

    def c 
    puts "#{self} - declared in instance method" # self is instance of A 
    class << self 
     puts "#{self} - declared in instance's singleton class" # now it's the A instance's singleton class 
    end 
    end 

end 

puts "All so far has happened simply by interpreting A's code" 

a = A.new 
A.a 
A.b 
a.c 

如果你想調用一個方法/從任何方面將消息發送到self,你能做到這一點明確地(例如self.method),或省略self作爲接收器 - 那麼按照慣例,消息的隱含接收者將是self

對此的一個有趣的方面是Ruby對private方法的解釋,該方法不同,例如,來自Java的概念private。 Ruby的私人方法僅通過發送使用self作爲隱式接收器的消息可調用,即

class A 

    def a 
    b 
    end 

    private 

    def b 
    puts "I'm private" 
    end 
end 

a = A.new 
a.a # => I'm private 

作品,而由

def a 
    self.b 
end 

替換方法的將引發異常。這意味着Java中很常見的東西

class A { 
    private boolean compareUs(A a1, A a2) { ... } 

    public boolean equals(A a1, A a2) { 
     return (a1.compareUs() == a2.compareUs()); 
    } 
} 

在Ruby中不起作用。愚蠢的例子,但只是爲了說明這一點:在Java中,我們可以訪問同一類的其他實例的私有方法,這在Ruby中是不可能的,因爲我們只能訪問當前的私有方法self

最後,使事情複雜一點,instance_evalclass_eval函數也將在執行過程中更改self的值。

+1

善良。什麼小說;) – 2011-07-13 00:42:08

+0

真棒的答案。謝謝:) –

+0

「return(a1.compareUs()== a2.compareUs())」真的嗎? compareUs()方法需要2個參數 – hihell

14

Ruby和Python實際上非常不同的語言(雖然他們有許多相似之處),即使Ruby有可寫看起來像Python中的語法(以列入end關鍵字);-)

Ruby是基於消息的(它受SmallTalk-80的嚴重影響)並且「消息」被髮送到對象。 Ruby支持一個隱式的接收器(明確稱爲self)的給定範圍。在紅寶石self不是一個變量,而是一個表達式,評估爲當前的對象上下文。

Python是基於財產的(因爲我缺乏一個更好的術語),因此與函數直接執行(而不是消息傳遞)執行時更類似於SELF和JavaScript。 Python沒有self關鍵字,並且它僅僅是約定,self被用作方法的第一個參數的名稱 - 這是Python在當前對象上下文周圍傳遞的方式。

快樂編碼。

9

在Python中,my_instance.a_method(an_argument)只是MyClass.a_method(my_instance, an_argument)的簡寫。這樣的MyClass.a_method定義應該考慮兩個參數:

class MyClass(object): 
    def a_method(self, an_argument): 
     print self # self (the instance) is available in the method 

由於PST說,使用變量名self的僅僅是一個慣例。你也可以有

class MyClass(object): 
    def a_method(this_instance, an_argument): 
     print this_instance 

和一切都會工作相同...但不這樣做。