Ruby Aus anderen Sprachen
Wenn Sie sich zum ersten Mal mit Ruby-Code beschäftigen, wird er Sie wahrscheinlich an andere Programmiersprachen erinnern, die Sie bereits verwendet haben. Das ist beabsichtigt. Ein Großteil der Syntax ist für Benutzer von Perl, Python und Java (unter anderem) vertraut, sodass das Erlernen von Ruby ein Kinderspiel ist, wenn Sie diese bereits kennen.
Dieses Dokument enthält zwei Hauptabschnitte. Der erste ist eine schnelle Zusammenfassung dessen, was Sie erwarten können, wenn Sie von Sprache X zu Ruby wechseln. Der zweite Abschnitt befasst sich mit den wichtigsten Sprachmerkmalen und wie diese mit dem verglichen werden können, was Sie bereits kennen.
Was zu erwarten ist: Sprache X zu Ruby
- Von Ruby nach C und C++
- Von Ruby nach Java
- Von Ruby nach Perl
- Von Ruby nach PHP
- Von Ruby nach Python
Wichtige Sprachmerkmale und einige Stolpersteine
Hier sind einige Hinweise und Tipps zu wichtigen Ruby-Funktionen, die Sie beim Erlernen von Ruby sehen werden.
Iteration
Zwei Ruby-Funktionen, die sich von dem, was Sie vielleicht zuvor gesehen haben, ein wenig unterscheiden und an die man sich erst gewöhnen muss, sind „Blocks“ und Iteratoren. Anstatt über einen Index zu loopen (wie bei C, C++ oder Java vor Version 1.5) oder über eine Liste zu loopen (wie bei Perl’s for (@a) {...} oder Python’s for i in aList: ...), werden Sie in Ruby sehr oft stattdessen sehen
some_list.each do |this_item|
# We're inside the block.
# deal with this_item.
endWeitere Informationen zu each (und seinen Freunden collect, find, inject, sort, usw.) finden Sie unter ri Enumerable (und dann ri Enumerable#some_method).
Alles hat einen Wert
Es gibt keinen Unterschied zwischen einem Ausdruck und einer Anweisung. Alles hat einen Wert, auch wenn dieser Wert nil ist. Das ist möglich
x = 10
y = 11
z = if x < y
true
else
false
end
z # => trueSymbole sind keine leichten Strings
Viele Ruby-Neulinge kämpfen damit, Symbole zu verstehen und wofür sie verwendet werden können.
Symbole können am besten als Identitäten beschrieben werden. Ein Symbol dreht sich alles um wer es ist, nicht was es ist. Starten Sie irb und sehen Sie den Unterschied
irb(main):001:0> :george.object_id == :george.object_id
=> true
irb(main):002:0> "george".object_id == "george".object_id
=> false
irb(main):003:0>Die Methode object_id gibt die Identität eines Objekts zurück. Wenn zwei Objekte dieselbe object_id haben, sind sie identisch (verweisen auf dasselbe Objekt im Speicher).
Sobald Sie ein Symbol einmal verwendet haben, verweist jedes Symbol mit denselben Zeichen auf dasselbe Objekt im Speicher. Für beliebige zwei Symbole, die dieselben Zeichen darstellen, stimmen die object_ids überein.
Betrachten Sie nun den String („george“). Die object_ids stimmen nicht überein. Das bedeutet, sie verweisen auf zwei verschiedene Objekte im Speicher. Immer wenn Sie einen neuen String verwenden, reserviert Ruby Speicher dafür.
Wenn Sie sich nicht sicher sind, ob Sie ein Symbol oder einen String verwenden sollen, überlegen Sie, was wichtiger ist: die Identität eines Objekts (z. B. ein Hash-Schlüssel) oder der Inhalt (im obigen Beispiel „george“).
Alles ist ein Objekt
„Alles ist ein Objekt“ ist keine Übertreibung. Sogar Klassen und ganze Zahlen sind Objekte, und Sie können mit ihnen dasselbe tun wie mit jedem anderen Objekt
# This is the same as
# class MyClass
# attr_accessor :instance_var
# end
MyClass = Class.new do
attr_accessor :instance_var
endVariable Konstanten
Konstanten sind nicht wirklich konstant. Wenn Sie eine bereits initialisierte Konstante ändern, wird eine Warnung ausgelöst, aber Ihr Programm wird nicht angehalten. Das soll jedoch nicht heißen, dass Sie Konstanten neu definieren sollten.
Namenskonventionen
Ruby erzwingt einige Namenskonventionen. Wenn ein Bezeichner mit einem Großbuchstaben beginnt, ist es eine Konstante. Wenn er mit einem Dollarzeichen ($) beginnt, ist es eine globale Variable. Wenn er mit @ beginnt, ist es eine Instanzvariable. Wenn er mit @@ beginnt, ist es eine Klassenvariable.
Methodennamen dürfen jedoch mit Großbuchstaben beginnen. Dies kann zu Verwirrung führen, wie das folgende Beispiel zeigt
Constant = 10
def Constant
11
endNun ist Constant 10, aber Constant() ist 11.
Schlüsselwortargumente
Wie in Python können seit Ruby 2.0 Methoden mit Schlüsselwortargumenten definiert werden
def deliver(from: "A", to: nil, via: "mail")
"Sending from #{from} to #{to} via #{via}."
end
deliver(to: "B")
# => "Sending from A to B via mail."
deliver(via: "Pony Express", from: "B", to: "A")
# => "Sending from B to A via Pony Express."Die universelle Wahrheit
In Ruby werden alle außer nil und false als wahr betrachtet. In C, Python und vielen anderen Sprachen gelten 0 und möglicherweise andere Werte wie leere Listen als falsch. Werfen Sie einen Blick auf den folgenden Python-Code (das Beispiel gilt auch für andere Sprachen)
# in Python
if 0:
print("0 is true")
else:
print("0 is false")Dies gibt „0 ist false“ aus. Das Äquivalent in Ruby
# in Ruby
if 0
puts "0 is true"
else
puts "0 is false"
endGibt „0 is true“ aus.
Zugriffsmodifikatoren gelten bis zum Ende des Gültigkeitsbereichs
Im folgenden Ruby-Code,
class MyClass
private
def a_method; true; end
def another_method; false; end
endErwarten Sie vielleicht, dass another_method öffentlich ist. Nicht so. Der Zugriffsmodifikator private gilt bis zum Ende des Gültigkeitsbereichs oder bis ein anderer Zugriffsmodifikator auftaucht, je nachdem, was zuerst eintritt. Standardmäßig sind Methoden öffentlich.
class MyClass
# Now a_method is public
def a_method; true; end
private
# another_method is private
def another_method; false; end
endpublic, private und protected sind eigentlich Methoden, daher können sie Parameter haben. Wenn Sie ihnen ein Symbol übergeben, wird die Sichtbarkeit dieser Methode geändert.
Methodenzugriff
In Java bedeutet public, dass eine Methode für jeden zugänglich ist. protected bedeutet, dass Instanzen der Klasse, Instanzen von abgeleiteten Klassen und Instanzen von Klassen im selben Paket darauf zugreifen können, aber sonst niemand, und private bedeutet, dass niemand außer den Instanzen der Klasse auf die Methode zugreifen kann.
Ruby unterscheidet sich leicht. public ist natürlich öffentlich. private bedeutet, dass die Methode(n) nur zugänglich sind, wenn sie ohne expliziten Empfänger aufgerufen werden können. Nur self darf der Empfänger eines privaten Methodenaufrufs sein.
protected ist diejenige, auf die man achten sollte. Eine geschützte Methode kann von Instanzen einer Klasse oder abgeleiteten Klasse aufgerufen werden, aber auch mit einer anderen Instanz als Empfänger. Hier ist ein Beispiel (angepasst aus The Ruby Language FAQ)
class Test
# public by default
def identifier
99
end
def ==(other)
identifier == other.identifier
end
end
t1 = Test.new # => #<Test:0x34ab50>
t2 = Test.new # => #<Test:0x342784>
t1 == t2 # => true
# now make `identifier' protected; it still works
# because protected allows `other' as receiver
class Test
protected :identifier
end
t1 == t2 # => true
# now make `identifier' private
class Test
private :identifier
end
t1 == t2
# NoMethodError: private method `identifier' called for #<Test:0x342784>Klassen sind offen
Ruby-Klassen sind offen. Sie können sie öffnen, ergänzen und jederzeit ändern. Sogar Kernklassen wie Integer oder Object, die Elternklasse aller Objekte. Ruby on Rails definiert eine Reihe von Methoden für den Umgang mit Zeit auf Integer. Achten Sie
class Integer
def hours
self * 3600 # number of seconds in an hour
end
alias hour hours
end
# 14 hours from 00:00 January 1st
# (aka when you finally wake up ;)
Time.mktime(2006, 01, 01) + 14.hours # => Sun Jan 01 14:00:00Lustige Methodennamen
In Ruby dürfen Methoden mit Fragezeichen oder Ausrufezeichen enden. Per Konvention enden Methoden, die Fragen beantworten, mit Fragezeichen (z. B. Array#empty?, die true zurückgibt, wenn der Empfänger leer ist). Potenziell „gefährliche“ Methoden enden per Konvention mit Ausrufezeichen (z. B. Methoden, die self oder die Argumente ändern, exit! usw.). Nicht alle Methoden, die ihre Argumente ändern, enden jedoch mit Ausrufezeichen. Array#replace ersetzt den Inhalt eines Arrays durch den Inhalt eines anderen Arrays. Es ergibt nicht viel Sinn, eine Methode wie diese zu haben, die self nicht verändert.
Singleton-Methoden
Singleton-Methoden sind pro-Objekt-Methoden. Sie sind nur auf dem Objekt verfügbar, auf dem Sie sie definiert haben.
class Car
def inspect
"Cheap car"
end
end
porsche = Car.new
porsche.inspect # => Cheap car
def porsche.inspect
"Expensive car"
end
porsche.inspect # => Expensive car
# Other objects are not affected
other_car = Car.new
other_car.inspect # => Cheap carFehlende Methoden
Ruby gibt nicht auf, wenn es eine Methode nicht finden kann, die auf eine bestimmte Nachricht reagiert. Es ruft die Methode method_missing mit dem Namen der nicht gefundenen Methode und den Argumenten auf. Standardmäßig löst method_missing eine NameError-Ausnahme aus, aber Sie können sie neu definieren, um sie besser an Ihre Anwendung anzupassen, und viele Bibliotheken tun dies. Hier ist ein Beispiel
# id is the name of the method called, the * syntax collects
# all the arguments in an array named 'arguments'
def method_missing(id, *arguments)
puts "Method #{id} was called, but not found. It has " +
"these arguments: #{arguments.join(", ")}"
end
__ :a, :b, 10
# => Method __ was called, but not found. It has these
# arguments: a, b, 10Der obige Code gibt nur die Details des Aufrufs aus, aber Sie können die Nachricht nach Belieben behandeln.
Nachrichtenübermittlung, keine Funktionsaufrufe
Ein Methodenaufruf ist eigentlich eine Nachricht an ein anderes Objekt
# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2Blöcke sind Objekte, sie wissen es nur noch nicht
Blöcke (eigentlich Closures) werden von der Standardbibliothek intensiv genutzt. Um einen Block aufzurufen, können Sie entweder yield verwenden oder ihn zu einem Proc machen, indem Sie ein spezielles Argument an die Argumentliste anhängen, so:
def block(&the_block)
# Inside here, the_block is the block passed to the method
the_block # return the block
end
adder = block { |a, b| a + b }
# adder is now a Proc object
adder.class # => ProcSie können Blöcke auch außerhalb von Methodenaufrufen erstellen, indem Sie Proc.new mit einem Block aufrufen oder die Methode lambda aufrufen.
Ähnlich sind auch Methoden Objekte im Entstehen
method(:puts).call "puts is an object!"
# => puts is an object!Operatoren sind syntaktischer Zucker
Die meisten Operatoren in Ruby sind nur syntaktischer Zucker (mit einigen Vorrangregeln) für Methodenaufrufe. Sie können beispielsweise die +-Methode von Integer überschreiben
class Integer
# You can, but please don't do this
def +(other)
self - other
end
endSie benötigen nicht C++’s operator+, usw.
Sie können sogar Array-ähnlichen Zugriff haben, wenn Sie die Methoden [] und []= definieren. Um die unären + und - (denken Sie an +1 und -2) zu definieren, müssen Sie die Methoden +@ bzw. -@ definieren. Die folgenden Operatoren sind jedoch kein syntaktischer Zucker. Sie sind keine Methoden und können nicht neu definiert werden.
=, .., ..., not, &&, and, ||, or, ::Außerdem sind +=, *= usw. nur Abkürzungen für var = var + other_var, var = var * other_var, usw. und können daher nicht neu definiert werden.
Mehr erfahren
Wenn Sie bereit für mehr Ruby-Wissen sind, besuchen Sie unseren Abschnitt Dokumentation.