Inhalt | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11

Offizielle Ruby FAQ

Wenn Sie Fehler melden oder Verbesserungen für diese FAQ vorschlagen möchten, besuchen Sie bitte unser GitHub-Repository und öffnen Sie ein Issue oder einen Pull Request.

Methoden

Wie wählt Ruby aus, welche Methode aufgerufen werden soll?

Ruby bindet alle Nachrichten dynamisch an Methoden. Zuerst sucht es nach Singleton-Methoden im Empfänger, dann nach Methoden, die in der eigenen Klasse des Empfängers definiert sind, und schließlich nach Methoden, die in den Oberklassen des Empfängers definiert sind (einschließlich aller Module, die möglicherweise gemischt wurden). Sie können die Reihenfolge der Suche anzeigen, indem Sie ClassName.ancestors anzeigen, was die Vorfahrenklassen und Module von ClassName auflistet.

Wenn nach dem Durchsuchen der Alternativen keine passende Methode gefunden wurde, versucht Ruby, eine Methode namens method_missing aufzurufen, und wiederholt denselben Suchvorgang, um sie zu finden. Dies ermöglicht es Ihnen, Nachrichten an unbekannte Methoden zu behandeln und wird oft verwendet, um dynamische Schnittstellen zu Klassen bereitzustellen.

module Emphasizable
  def emphasize
    "**#{self}**"
  end
end

class String
  include Emphasizable
end

String.ancestors
  # => [String, Emphasizable, Comparable, Object, Kernel, BasicObject]

"Wow!".emphasize  # => "**Wow!**"

Wenn nach der Methode emphasize gesucht wird und diese in der Klasse String nicht gefunden wird, sucht Ruby als nächstes im Modul Emphasizable.

Um eine Methode zu überschreiben, die bereits in der Klasse des Empfängers existiert, z. B. String#capitalize, müssen Sie das Modul in die Ahnenkette vor dieser Klasse einfügen, indem Sie prepend verwenden.

module PrettyCapitalize
  def capitalize
    "**#{super}**"
  end
end

class String
  prepend PrettyCapitalize
end

String.ancestors
  # => [PrettyCapitalize, String, Comparable, Object, Kernel, BasicObject]

"hello".capitalize  # => "**Hello**"

Sind +, -, *, … Operatoren?

+, - und ähnliche sind keine Operatoren, sondern Methodenaufrufe. Sie können daher durch neue Definitionen überladen werden.

class MyString < String
  def -(other)
    self[0...other.size]  # self truncated to other's size
  end
end

Die folgenden sind jedoch integrierte Kontrollstrukturen, keine Methoden, die nicht überschrieben werden können.

=, .., ..., not, ||, &&, and, or, ::

Um die unären Operatoren + und - zu überladen oder zu definieren, müssen Sie +@ und -@ als Methodennamen verwenden.

= wird verwendet, um eine Methode zu definieren, die ein Attribut des Objekts setzt.

class Test
  def attribute=(val)
    @attribute = val
  end
end

t = Test.new
t.attribute = 1

Wenn Operatoren wie + und - definiert sind, handhabt Ruby automatisch die Selbstzuweisungsformen (+=, -= usw.).

Wo sind ++ und --?

Ruby hat keine Autoinkrement- und Autodekrement-Operatoren. Sie können stattdessen += 1 und -= 1 verwenden.

Was ist eine Singleton-Methode?

Eine Singleton-Methode ist eine Instanzmethode, die einem bestimmten Objekt zugeordnet ist.

Sie erstellen eine Singleton-Methode, indem Sie das Objekt in die Definition aufnehmen.

class Foo; end

foo = Foo.new
bar = Foo.new

def foo.hello
  puts "Hello"
end

foo.hello
bar.hello

Erzeugt

Hello
prog.rb:11:in `<main>': undefined method `hello' for #<Foo:0x000000010f5a40> (NoMethodError)

Singleton-Methoden sind nützlich, wenn Sie einem Objekt eine Methode hinzufügen möchten und das Erstellen einer neuen Unterklasse nicht angebracht ist.

All diese Objekte sind in Ordnung, aber hat Ruby einfache Funktionen?

Ja und nein. Ruby hat Methoden, die wie Funktionen in Sprachen wie C oder Perl aussehen.

def hello(name)
  puts "Hello, #{name}!"
end

hello("World")

Erzeugt

Hello, World!

Dies sind jedoch tatsächlich Methodenaufrufe, bei denen der Empfänger weggelassen wird. In diesem Fall nimmt Ruby an, dass der Empfänger self ist.

Somit ähnelt hello einer Funktion, ist aber tatsächlich eine Methode, die zur Klasse Object gehört und als Nachricht an den versteckten Empfänger self gesendet wird. Ruby ist eine reine objektorientierte Sprache.

Natürlich können Sie solche Methoden wie Funktionen verwenden.

Woher kommen all diese funktionsähnlichen Methoden?

Fast alle Klassen in Ruby sind von der Klasse Object abgeleitet. Die Definition der Klasse Object mischt die im Modul Kernel definierten Methoden. Diese Methoden sind daher in jedem Objekt des Systems verfügbar.

Auch wenn Sie ein einfaches Ruby-Programm ohne Klassen schreiben, arbeiten Sie tatsächlich innerhalb der Klasse Object.

Kann ich auf Instanzvariablen eines Objekts zugreifen?

Die Instanzvariablen eines Objekts (Variablen, die mit @ beginnen) sind außerhalb des Objekts nicht direkt zugänglich. Dies fördert eine gute Kapselung. Ruby erleichtert es Ihnen jedoch, Accessoren für diese Instanzvariablen zu definieren, so dass Benutzer Ihrer Klasse Instanzvariablen wie Attribute behandeln können. Verwenden Sie einfach eine oder mehrere der Optionen attr_reader, attr_writer oder attr_accessor.

class Person
  attr_reader   :name           # read only
  attr_accessor :wearing_a_hat  # read/write

  def initialize(name)
    @name = name
  end
end

p = Person.new("Dave")
p.name           # => "Dave"
p.wearing_a_hat  # => nil
p.wearing_a_hat = true
p.wearing_a_hat  # => true

Sie können auch eigene Accessor-Funktionen definieren (vielleicht zur Validierung oder zur Behandlung abgeleiteter Attribute). Der Lese-Accessor ist einfach eine Methode, die keine Parameter annimmt, und der Zuweisungs-Accessor ist ein Methodenname, der auf = endet und einen einzelnen Parameter annimmt. Obwohl zwischen dem Methodennamen und dem = in der Methodendefinition kein Leerzeichen stehen kann, können Sie dort Leerzeichen einfügen, wenn Sie die Methode aufrufen, sodass sie wie jede andere Zuweisung aussieht. Sie können auch Selbstzuweisungen wie += und -= verwenden, solange die entsprechenden +- oder --Methoden definiert sind.

Was ist der Unterschied zwischen private und protected?

Das Sichtbarkeits-Schlüsselwort private macht eine Methode nur in Funktionsform, ohne expliziten Empfänger, aufrufbar, so dass sie nur self als Empfänger haben kann. Eine private Methode kann nur innerhalb der Klasse, in der die Methode definiert wurde, oder in ihren Unterklassen aufgerufen werden.

class Test
  def foo
    99
  end

  def test(other)
    p foo
    p other.foo
  end
end

t1 = Test.new
t2 = Test.new

t1.test(t2)

# Now make `foo' private

class Test
  private :foo
end

t1.test(t2)

Erzeugt

99
99
99
prog.rb:8:in `test': private method `foo' called for #<Test:0x00000000b57a48> (NoMethodError)
        from prog.rb:23:in `<main>'

Geschützte Methoden sind ebenfalls nur aus ihrer eigenen Klasse oder deren Unterklassen aufrufbar, können aber sowohl in Funktionsform als auch mit einem Empfänger aufgerufen werden. Zum Beispiel

def <=>(other)
  age <=> other.age
end

wird kompiliert, wenn age eine geschützte Methode ist, aber nicht, wenn sie privat ist.

Diese Funktionen helfen Ihnen, den Zugriff auf die Interna Ihrer Klasse zu steuern.

Wie kann ich die Sichtbarkeit einer Methode ändern?

Sie ändern die Sichtbarkeit von Methoden mithilfe von private, protected und public. Wenn sie ohne Parameter während einer Klassendefinition verwendet werden, beeinflussen sie die Sichtbarkeit nachfolgender Methoden. Wenn sie mit Parametern verwendet werden, ändern sie die Sichtbarkeit der benannten Methoden.

class Foo
  def test
    puts "hello"
  end
  private :test
end

foo = Foo.new
foo.test

Erzeugt

prog.rb:9:in `<main>': private method `test' called for #<Foo:0x0000000284dda0> (NoMethodError)

Sie können eine Klassenmethode privat machen, indem Sie private_class_method verwenden.

class Foo
  def self.test
    puts "hello"
  end
  private_class_method :test
end

Foo.test

Erzeugt

prog.rb:8:in `<main>': private method `test' called for Foo:Class (NoMethodError)

Die Standard-Sichtbarkeit für Methoden, die in einer Klasse definiert sind, ist öffentlich. Die Ausnahme ist die Initialisierungsmethode der Instanz, initialize.

Methoden, die auf der obersten Ebene definiert sind, sind ebenfalls standardmäßig öffentlich.

Kann ein Bezeichner, der mit einem Großbuchstaben beginnt, ein Methodennamen sein?

Ja, das kann er, aber wir tun das nicht leichtfertig! Wenn Ruby einen großgeschriebenen Namen gefolgt von einem Leerzeichen sieht, wird es wahrscheinlich (abhängig vom Kontext) davon ausgehen, dass es sich um eine Konstante und nicht um einen Methodennamen handelt. Wenn Sie also großgeschriebene Methodennamen verwenden, denken Sie immer daran, Parameterlisten in Klammern zu setzen, und setzen Sie die Klammern immer direkt neben dem Methodennamen ohne Leerzeichen dazwischen. (Dieser letzte Vorschlag ist sowieso eine gute Idee!)

Das Aufrufen von super führt zu einem ArgumentError.

Das Aufrufen von super ohne Parameter in einer Methode übergibt alle Argumente dieser Methode an eine Methode mit demselben Namen in einer Oberklasse. Wenn die Anzahl der Argumente der ursprünglichen Methode nicht mit der der übergeordneten Methode übereinstimmt, wird ein ArgumentError ausgelöst. Um dies zu umgehen, rufen Sie einfach super auf und übergeben Sie eine geeignete Anzahl von Argumenten.

Wie kann ich die Methode mit demselben Namen zwei Ebenen höher aufrufen?

super ruft die Methode mit demselben Namen eine Ebene höher auf. Wenn Sie eine Methode in einem weiter entfernten Vorfahren überschreiben, verwenden Sie alias, um ihr einen neuen Namen zu geben, bevor Sie sie mit Ihrer Methodendefinition verdecken. Sie können sie dann über diesen Alias-Namen aufrufen.

Wie kann ich eine ursprüngliche eingebaute Methode aufrufen, nachdem ich sie neu definiert habe?

Innerhalb der Methodendefinition können Sie super verwenden. Sie können auch alias verwenden, um ihr einen alternativen Namen zu geben. Schließlich können Sie die ursprüngliche Methode als Singleton-Methode von Kernel aufrufen.

Was ist eine destruktive Methode?

Eine destruktive Methode ist eine, die den Zustand eines Objekts verändert. String, Array, Hash und andere haben solche Methoden. Oft gibt es zwei Versionen einer Methode, eine mit einem einfachen Namen, die andere mit demselben Namen, aber gefolgt von !. Die einfache Version erstellt eine Kopie des Empfängers, nimmt die Änderung an ihr vor und gibt die Kopie zurück. Die "Bang"-Version (mit dem !) modifiziert den Empfänger direkt.

Seien Sie sich jedoch bewusst, dass es eine beträchtliche Anzahl destruktiver Methoden gibt, die kein ! haben, einschließlich Zuweisungsmethoden (name=), Array-Zuweisungen ([]=) und Methoden wie Array.delete.

Warum können destruktive Methoden gefährlich sein?

Denken Sie daran, dass die Zuweisung in den meisten Fällen nur Objektverweise kopiert und die Parameterübergabe einer Zuweisung gleichkommt. Das bedeutet, dass Sie mehrere Variablen haben können, die auf dasselbe Objekt verweisen. Wenn eine dieser Variablen verwendet wird, um eine destruktive Methode aufzurufen, wird das von allen referenzierte Objekt geändert.

def foo(str)
  str.sub!(/foo/, "baz")
end

obj = "foo"
foo(obj)     # => "baz"
obj          # => "baz"

In diesem Fall wird das tatsächliche Argument geändert.

Kann ich mehrere Werte aus einer Methode zurückgeben?

Ja und nein.

def m1
  return 1, 2, 3
end

def m2
  [1, 2, 3]
end

m1  # => [1, 2, 3]
m2  # => [1, 2, 3]

Somit wird nur eine Sache zurückgegeben, aber diese Sache kann ein beliebig komplexes Objekt sein. Im Falle von Arrays können Sie mehrere Zuweisungen verwenden, um den Effekt mehrerer Rückgabewerte zu erzielen. Zum Beispiel

def foo
  [20, 4, 17]
end

a, b, c = foo
a              # => 20
b              # => 4
c              # => 17