2012-05-10 6 views
40

Zum Beispiel habe ich den Methodennamen bundler? im folgenden Ausschnitt gefunden, und weiß nicht, ob das ? Zeichen ein spezialisiertes Schlüsselwort oder nur ein Teil des Methodennamens ist.Was sind die Einschränkungen für Methodennamen in 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 

Antwort

72

Methodennamen in Ruby kann Großbuchstaben enthalten, und Kleinbuchstaben, Zahlen, unterstreicht _ und die Punktierung unterzeichnet !, ?, =.

Ein Methodenname darf nicht mit einer Nummer beginnen, und die Zeichen !, ? und = können nur am Ende erscheinen.

Nicht-ASCII-Zeichen können in einem Methodennamen verwendet werden, dies kann jedoch zu sehr verwirrenden Situationen führen und sollte nicht allgemein üblich sein.

Es empfiehlt sich, den Methodennamen mit einem Kleinbuchstaben zu beginnen, da er nicht zwingend ist, da Namen, die mit Großbuchstaben beginnen, Konstanten in Ruby sind. Es ist immer noch möglich, einen konstanten Namen für eine Methode zu verwenden, aber Sie werden es nicht ohne Klammern aufrufen Lage sein, weil die interpeter wird für den Namen als Konstante Nachschau:

def Capital 
    nil 
end 

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

Einige sehr breit und konsequent verwendet Konventionen bei der Definition von Methodennamen sind:

  1. Methodennamen sind voll Abwärts Fall mit Unterstrichen _ als Separatoren für Worte in den Namen (zB Math::sqrt, Array#each_index, ...).

  2. Prädikate haben ein Fragezeichen ? als letztes Zeichen (z Array#empty?, Hash#has_key?, ...). Während Prädikate normalerweise boolesche Werte zurückgeben, ist dies nicht immer der Fall: diese Methoden müssen nur nil oder false zurückgeben, wenn das Prädikat false ergibt, ansonsten einen anderen Wert (zB File::size? gibt nil zurück, wenn die Datei nicht existiert, die Größe der Datei als Integer ansonsten).

  3. Methoden, die den Status des Objekts ändern, auf dem sie aufgerufen werden, oder die ein ungewöhnliches Verhalten aufweisen, haben ein Ausrufezeichen ! als letztes Zeichen; Diese Methoden werden manchmal als Mutatoren bezeichnet, weil sie normalerweise destruktive oder In-Place-Versionen anderer Methoden sind (z. B. Array#sort!, Array#slice!, ...).

  4. Setters haben ein Gleichheitszeichen = als letzte Zeichen (z.B. Array#[]=, ...); Ruby interpeter bietet syntaktischen Zucker für Invokation von Setter-Methoden:

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

Rubin auch Betreiber mit dem Operator Symbol als Methodennamen definieren kann:

╔═══════════════════════════╦═════════════════════════════════════════════╦═══════╗ 
║ 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 ║ 
╚═══════════════════════════╩═════════════════════════════════════════════╩═══════╝ 

unärer Operator Methoden keine Argumente übergeben; Binäre Operatormethoden übergeben ein Argument und operieren darauf und auf self.

Es ist wichtig, sich streng an die Genauigkeit der Bediener zu halten; Während es möglich ist, Operatormethoden mit einer anderen Arität zu definieren (z. B. eine + Methode, die zwei Argumente akzeptiert), würde Ruby es nicht erlauben, die Methode mit Operatorsyntax aufzurufen (sie würde jedoch mit Punktsyntax arbeiten).

Es ist gute Praxis, die ursprüngliche Semantik der Operatoren so weit wie möglich einzuhalten: Es sollte für jemanden intuitiv sein, der die ursprüngliche Bedeutung des Operators kennt, wie er mit benutzerdefinierten Klassen funktioniert.

Die Sprache bietet auch syntaktischen Zucker für den speziellen, nicht-Operator , [] Verfahren, das normalerweise Array und Hash-Wertes verwendet wird, für den Zugriff. Die [] Methode kann beliebig definiert werden.

Für jeden binären Operator in der Tabelle, außer Reihenfolge, Gleichheit, Vergleich und Mustervergleich, bietet Ruby auch Abkürzung für abgekürzte Zuordnung (z. B. x += y erweitert auf x = x + y); Sie können sie nicht als Methoden definieren, aber Sie können ihr Verhalten ändern, indem Sie die Operatoren definieren, auf denen sie basieren.

Keines dieser Zeichen kann innerhalb normaler Methodennamen verwendet werden (z. B. do&print oder start-up sind keine gültigen Methodennamen).

+1

Große Antwort! Als kleine Anmerkung: Es ist üblich, dass Prädikatmethoden (mit einem '?') Falsche ("nil" oder "false") oder truethy (alles andere) Werte zurückgeben, nicht notwendig 'true' und' false'. Der Rückgabewert soll in "if" -Anweisungen verwendet werden, wo er sich verhält, als ob er "true" und "false" wäre, aber der tatsächliche Rückgabewert ist oft nicht Teil der intendierten Methodenschnittstelle, sondern nur truethy oder falsey. –

+0

Danke für den Rat, habe ich entsprechend bearbeitet. –

+0

Es gibt auch einige Zeichen, die nur als Name der gesamten Methode verwendet werden können, dh Sie können Methoden namens - + * **/(wenn Sie diese Operatoren überladen) definieren, aber keine Methode namens foo + bar –

0

Die Zeichen zugelassen sind: a-Z,, 0-9 solange nicht am Anfang, _ und ? (für Boolesche Funktionen) und ! (für destruktive Funktionen) und = (für Etter).

2

Methodennamen können in !, ? oder = enden. Unterstriche sind ebenfalls erlaubt. Daneben gibt es mehrere Methoden, die wie Operatoren aussehen (z. B. +, *, >>, []), die Sie für Ihre eigenen Klassen definieren können.

4

Was andere sagen gilt für die eingebauten Syntax, aber es scheint, kann keine Back-End-Beschränkungen zu sein, was verwendet werden, wenn Sie Methoden verwenden, wie define_method + send:

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

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

Diese Tatsache kann nützlich sein: zum Beispiel Rails' ActiveSupport::Testing::Declarative.test Methode verwendet es, um nicht komplexe Konvertierungen auf zu tun:

test 'Some Controller#Method' do 

zu einem gesünderen Namen, der mit einem anderen Test in Konflikt geraten könnte genannt:

test 'Some Controller_Method' do 

Dies ist auf der Testing Guide erwähnt.

Neugier: ein ähnliches geschieht in Java, wo der Bytecode Methodenname Art und Weise mehr Auswahl als die Java-Sprache gibt: Why does the JVM allow us to name a function starting with a digit in bytecode?

2

eins hinzufügen: Sie können ein Objekt auch sagen, ein Verfahren mit nicht laufen Name auf allen und es wird versuchen, eine Methode call namens aufzurufen:

#!/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 

es nicht wirklich jede Methode call auf Object definiert benannt ist, aber es gibt eine auf der Method und Proc Klassen.

In einigen Sprachen ist () ein Operator für den Funktionsaufruf, und das scheint ziemlich ähnlich zu dem zu sein, was hier passiert.

Dies wird z.B. in Rails' JBuilder:

https://github.com/rails/jbuilder

Es wird auf Seite 196 des O'Reilly Ruby-Buch dokumentiert:

Ruby 1.9 bietet eine zusätzliche Möglichkeit, einen Proc Objekt aufzurufen; als Alternative Klammern zum Quadrat, können Sie Klammern mit einem Punkt voran verwenden:

z = f.(x,y) 

.() sieht aus wie ein Methodenaufruf den Namen der Methode fehlt. Dies ist kein Operator, der definiert werden kann, sondern ein syntaktischer Zucker, der die call-Methode aufruft. Es kann mit jedem Objekt verwendet werden, das eine call-Methode definiert und ist nicht auf Proc Objekte beschränkt.

Verwandte Themen