2012-05-10 18 views
40

例如,我在下面的代碼片段中找到方法名稱bundler?,並且不知道?字符是專用關鍵字還是方法名稱的一部分。Ruby中方法名稱的限制是什麼?

# This is a predicate useful for the doc:guides task of applications. 
def bundler? 
    # Note that rake sets the cwd to the one that contains the Rakefile 
    # being executed. 
    File.exists?('Gemfile') 
end 

回答

72

Ruby中的方法名可能包含大寫和小寫字母,數字,下劃線_和標點符號!,?,=

方法名稱不能以數字開頭,字符!,?=只能出現在最後。

非ASCII字符可以在方法名稱中使用,但是這可能會導致非常混亂的情況下,不應該是普遍的做法。

這是很好的做法,而不是強制性的,用小寫字母開頭的方法的名稱,因爲以大寫字母開頭的名稱是用Ruby常量。它仍然可以使用恆定的名稱的方法,但你不能調用它沒有括號,因爲interpeter將查找的名稱爲常量:

def Capital 
    nil 
end 

Capital # NameError: uninitialized constant Capital 
Capital() # => nil 

一些非常廣泛和堅持使用約定當定義方法的名稱是:

  1. 方法名是全降的情況下,用下劃線_作爲的話將其命名爲分隔符(如Math::sqrtArray#each_index,...)。

  2. 謂詞有一個問號?作爲最後一個字符(例如Array#empty?Hash#has_key?,...)。雖然謂語通常返回布爾值,這並非總是如此:這些方法只需要返回nilfalse如果謂詞爲假,任何其他值,否則(例如File::size?返回nil如果文件不存在,的大小否則爲Integer)。

  3. 修改其被調用對象的狀態或具有不正常行爲的方法的最後一個字符爲感嘆號!;這種方法有時被稱爲變異體,因爲它們通常是破壞性或其他方法的原地版本(例如Array#sort!,Array#slice!,...)。

  4. 塞特斯具有等號=作爲最後一個字符(例如Array#[]=,...);紅寶石interpeter提供語法糖用於setter方法invokation:

    a = [4, 5, 6] 
    a[0] = 3 # Shorthand for a.[]=(0, 3) 
    

紅寶石還允許使用操作符號作爲方法名定義操作符:

╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗ 
║ Operators (by precedence) ║     Operations     ║ Arity ║ 
╠═══════════════════════════╬═════════════════════════════════════════════╬═══════╣ 
║ ! ~ +      ║ Boolean NOT, bitwise complement, unary plus ║  1 ║ 
║       ║ (define with method name [email protected], Ruby 1.9+)  ║  ║ 
║       ║            ║  ║ 
║ **      ║ Exponentiation        ║  2 ║ 
║       ║            ║  ║ 
║ -       ║ Unary minus (define with method name [email protected]) ║  1 ║ 
║       ║            ║  ║ 
║ */%      ║ Multiplication, division, modulo   ║  2 ║ 
║       ║            ║  ║ 
║ + -      ║ Addition, subtraction      ║  2 ║ 
║       ║            ║  ║ 
║ << >>      ║ Bitwise shift        ║  2 ║ 
║       ║            ║  ║ 
║ &       ║ Bitwise AND         ║  2 ║ 
║       ║            ║  ║ 
║ |^      ║ Bitwise OR, Bitwise XOR      ║  2 ║ 
║       ║            ║  ║ 
║ < <= => >     ║ Ordering         ║  2 ║ 
║       ║            ║  ║ 
║ == === != =~ !~ <=>  ║ Equality, pattern matching, comparison  ║  2 ║ 
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝ 

一元運算符的方法是沒有任何爭論;二元運算符方法傳遞一個參數,並對其進行操作並在self上運行。

嚴格遵守運營商的元數是很重要的;雖然可以使用不同的參數定義運算符方法(例如,帶有兩個參數的+方法),但Ruby不允許您使用運算符語法調用該方法(但它可以使用點語法)。

這是堅持以儘可能多地運營商的原始語義很好的做法:它應該是直觀的人誰知道它是如何使用用戶定義的類運營商的本義。

該語言還爲特殊語言提供語法糖,非運算符,[]通常用於訪問數組和散列值的方法。 []方法可以用任意的arity來定義。對於表中的每個二元運算符,除了排序,相等,比較和模式匹配外,Ruby還提供縮寫賦值的簡寫(例如,x += y擴展爲x = x + y);你不能將它們定義爲方法,但你可以改變它們的定義它們所基於的操作符的行爲。

這些字符都不能在常規方法名稱內使用(例如,do&printstart-up不是有效的方法名稱)。

+1

很好的答案!稍作說明:謂詞方法(帶'?')返回falsey('nil'或'false')或truethy(其他所有)值是習慣性的,而不是必須的'true'和'false'。返回值旨在用於'if'語句,其行爲就像'true'和'false'一樣,但實際返回值通常不是預期的方法接口的一部分,只是它是真實或虛假的屬性。 –

+0

感謝您的建議,我做了相應的編輯。 –

+0

還有一些字符只能用作整個方法的名字,也就是說你可以定義一個名爲 - + * ** /(如果你重載了那些運算符)的方法,而不是一個叫做foo + bar的方法 –

0

允許的字符是:a-Z,0-9只要不是開頭,_,並?(布爾函數)和!(破壞性功能)和=(對於設置器)。

2

方法名稱可以在!,?=處結束。下劃線也是允許的。除此之外,還有幾種看起來像您可以爲您自己的類定義的運算符(例如,+,*,>>,[])。

4

別人說什麼是真正的內置語法,但有似乎是,如果你使用的方法是什麼,可以使用任何後端限制像define_method + send

define_method(:'$% ^&') { 0 } 
define_method(:'你好') { 1 } 

send(:'$% ^&') == 0 or raise 
send(:'你好') == 1 or raise 

這個事實可以是有用的:例如Rails的ActiveSupport::Testing::Declarative.test方法使用它,以免做複雜的轉換:

test 'Some Controller#Method' do 

一個理智的名字,這可能與另一個名爲測試衝突:

test 'Some Controller_Method' do 

這是在Testing Guide上提到的。

好奇:類似的事情發生在Java中,當字節碼方法名讓位更多的選擇比Java語言:Why does the JVM allow us to name a function starting with a digit in bytecode?

2

要補充說明一兩件事:你也可以告訴一個對象與運行的方法沒有名都,它會嘗試調用的方法命名call

#!/usr/bin/env ruby 

class Foo 

=begin 
    def call(*args) 
    puts "received call with #{args.join(' ')}" 
    end 
=end 

    def method_missing(m, *args, &block) 
    puts "received method_missing on `#{m}(#{args.join(', ')})`" 
    end 

end 

f = Foo.new 
f.('hi')    # Not a syntax error! method_missing with m of :call 
f.send :'', 'hmm' # method_missing with m set to :'' 
f.send nil, 'bye' # raises an error 

沒有實際命名上Object定義call任何方法,但有一個在MethodProc類。

在某些語言中,()是一個函數調用的運算符,它看起來與這裏發生的事情非常相似。

這用於例如在Rails的JBuilder中:

https://github.com/rails/jbuilder

據記載O'Reilly的紅寶石書的196頁:

的Ruby 1.9提供了一個額外的方式來調用一個Proc對象;作爲替代方括號中,你可以使用一個週期前綴括號:

z = f.(x,y) 

.()看起來像一個方法調用缺少方法名。這不是一個可以定義的運算符,而是調用call方法的語法糖。它可以用於定義方法的任何對象,並且不限於Proc對象。

相關問題