Von Ruby nach C und C++
Es ist schwierig, eine Aufzählung zu schreiben, die beschreibt, wie sich Ihr Code in Ruby von C oder C++ unterscheidet, da der Unterschied ziemlich groß ist. Ein Grund dafür ist, dass die Ruby-Laufzeitumgebung so viel für Sie erledigt. Ruby scheint dem Prinzip von C „kein versteckter Mechanismus“ so weit wie möglich zu widersprechen – der eigentliche Sinn von Ruby ist es, die Arbeit des Menschen zu erleichtern, auf Kosten der Laufzeitumgebung, die mehr Arbeit schultern muss. Sofern Sie Ihren Code nicht zur Optimierung profilen, müssen Sie sich bei der Verwendung von Ruby keinerlei Gedanken über „das Glücklichmachen Ihres Compilers“ machen.
Dennoch können Sie erwarten, dass Ihr Ruby-Code viel langsamer ausgeführt wird als „äquivalenter“ C- oder C++-Code. Gleichzeitig werden Sie sich über die Geschwindigkeit, mit der Sie ein Ruby-Programm zum Laufen bringen können, sowie über die geringe Anzahl von Codezeilen, die zu seiner Erstellung erforderlich sind, wundern. Ruby ist viel, viel einfacher als C++ – es wird Sie hoffnungslos verwöhnen.
Ruby ist dynamisch typisiert, nicht statisch typisiert – die Laufzeitumgebung erledigt so viel wie möglich zur Laufzeit. Sie müssen zum Beispiel nicht wissen, mit welchen Modulen Ihr Ruby-Programm „verknüpft“ wird (d. h. welche geladen und verwendet werden) oder welche Methoden es im Voraus aufruft.
Glücklicherweise erweist sich, dass Ruby und C eine gesunde symbiotische Beziehung haben. Ruby unterstützt sogenannte „Erweiterungsmodule“. Dies sind Module, die Sie von Ihren Ruby-Programmen aus verwenden können (und die von außen wie jedes andere Ruby-Modul aussehen und sich auch so verhalten), die aber in C geschrieben sind. Auf diese Weise können Sie die leistungskritischen Teile Ihrer Ruby-Software abgrenzen und sie zu reinem C einschmelzen.
Und natürlich ist Ruby selbst in C geschrieben.
Gemeinsamkeiten mit C
Wie bei C, in Ruby,…
- Sie können prozedural programmieren, wenn Sie möchten (aber es wird im Hintergrund immer noch objektorientiert sein).
- Die meisten Operatoren sind gleich (einschließlich der zusammengesetzten Zuweisung und auch der bitweisen Operatoren). Ruby hat jedoch kein
++oder--. - Sie haben
__FILE__und__LINE__. - Sie können auch Konstanten haben, obwohl es kein spezielles Schlüsselwort
constgibt. Die Konstanz wird stattdessen durch eine Namenskonvention erzwungen – Namen, die mit einem Großbuchstaben beginnen, sind für Konstanten. - Strings werden in doppelten Anführungszeichen gesetzt.
- Strings sind veränderbar.
- Genau wie Manpages können Sie die meisten Dokumentationen in Ihrem Terminalfenster lesen – allerdings mit dem Befehl
ri. - Sie haben die gleiche Art von Kommandozeilendebugger zur Verfügung.
Gemeinsamkeiten mit C++
Wie bei C++, in Ruby,…
- Sie haben größtenteils die gleichen Operatoren (sogar
::).<<wird oft zum Anhängen von Elementen an eine Liste verwendet. Eine Anmerkung jedoch: Mit Ruby verwenden Sie niemals->– es ist immer nur.. public,privateundprotectederfüllen ähnliche Aufgaben.- Die Syntax für die Vererbung ist immer noch nur ein Zeichen, aber es ist
<anstelle von:. - Sie können Ihren Code in „Module“ einteilen, ähnlich wie
namespacein C++ verwendet wird. - Ausnahmen funktionieren auf ähnliche Weise, obwohl die Schlüsselwortnamen geändert wurden, um die Unschuldigen zu schützen.
Unterschiede zu C
Im Gegensatz zu C, in Ruby,…
- Sie müssen Ihren Code nicht kompilieren. Sie führen ihn einfach direkt aus.
- Objekte sind stark typisiert (und Variablennamen selbst haben keine Typen).
- Es gibt keine Makros oder Präprozessoren. Keine Casts. Keine Zeiger (noch Zeigerarithmetik). Keine Typedefs, sizeof oder Enums.
- Es gibt keine Header-Dateien. Sie definieren Ihre Funktionen (normalerweise als „Methoden“ bezeichnet) und Klassen einfach in den Hauptquellcode-Dateien.
- Es gibt kein
#define. Verwenden Sie stattdessen einfach Konstanten. - Alle Variablen leben auf dem Heap. Darüber hinaus müssen Sie sie nicht selbst freigeben – der Garbage Collector kümmert sich darum.
- Argumente an Methoden (d.h. Funktionen) werden by-value übergeben, wobei die Werte immer Objekt-Referenzen sind.
- Es ist
require 'foo'anstelle von#include <foo>oder#include "foo". - Sie können nicht auf Assembler-Ebene absteigen.
- Es gibt keine Semikolons am Ende von Zeilen.
- Sie verzichten auf Klammern für die Bedingungsausdrücke von
ifundwhile. - Klammern für Methodenaufrufe (d.h. Funktionsaufrufe) sind oft optional.
- Sie verwenden normalerweise keine geschweiften Klammern – beenden Sie mehrzeilige Konstrukte (wie
while-Schleifen) einfach mit dem Schlüsselwortend. - Das Schlüsselwort
doist für sogenannte „Blocks“. Es gibt keine „do-Anweisung“ wie in C. - Der Begriff „Block“ bedeutet etwas anderes. Es handelt sich um einen Codeblock, den Sie mit einem Methodenaufruf verknüpfen, damit der Methodenkörper während der Ausführung den Block aufrufen kann.
- Es gibt keine Variablendeklarationen. Sie weisen neuen Namen einfach auf der Fliege Werte zu, wenn Sie sie benötigen.
- Wenn auf Wahrheit getestet wird, werden nur
falseundnilzu einem falschen Wert ausgewertet. Alles andere ist wahr (einschließlich0,0.0und"0"). - Es gibt kein
char– das sind nur 1-Buchstaben-Strings. - Strings enden nicht mit einem Nullbyte.
- Array-Literale werden in eckigen Klammern anstelle von geschweiften Klammern geschrieben.
- Arrays werden einfach automatisch größer, wenn Sie mehr Elemente hineinstopfen.
- Wenn Sie zwei Arrays addieren, erhalten Sie ein neues und größeres Array (natürlich auf dem Heap zugewiesen) anstelle von Zeigerarithmetik.
- Meistens ist alles ein Ausdruck (das heißt, Dinge wie
while-Anweisungen werden tatsächlich zu einem rvalue ausgewertet).
Unterschiede zu C++
Im Gegensatz zu C++, in Ruby,…
- Es gibt keine expliziten Referenzen. Das heißt, in Ruby ist jede Variable nur ein automatisch dereferenzierter Name für ein bestimmtes Objekt.
- Objekte sind stark, aber dynamisch typisiert. Die Laufzeitumgebung ermittelt zur Laufzeit, ob der Methodenaufruf tatsächlich funktioniert.
- Der „Konstruktor“ heißt
initializeanstelle des Klassennamens. - Alle Methoden sind immer virtuell.
- Namen von „Klassen“- (statischen) Variablen beginnen immer mit
@@(wie in@@total_widgets). - Sie greifen nicht direkt auf Member-Variablen zu – der gesamte Zugriff auf öffentliche Member-Variablen (in Ruby als Attribute bekannt) erfolgt über Methoden.
- Es ist
selfanstelle vonthis. - Einige Methoden enden mit einem „?“ oder einem „!“. Das ist tatsächlich Teil des Methodennamens.
- Es gibt keine Mehrfachvererbung an sich. Ruby hat jedoch „Mixins“ (d. h. Sie können alle Instanzmethoden eines Moduls „erben“).
- Es gibt einige erzwungene Groß-/Kleinschreibungs-Konventionen (z. B. Klassennamen beginnen mit einem Großbuchstaben, Variablennamen mit einem Kleinbuchstaben).
- Klammern für Methodenaufrufe sind meist optional.
- Sie können eine Klasse jederzeit wieder öffnen und weitere Methoden hinzufügen.
- Es besteht keine Notwendigkeit für C++-Templates (da Sie jeder gegebenen Variablen jeden Objekttyp zuweisen können und die Typen ohnehin zur Laufzeit ermittelt werden). Auch kein Casting.
- Die Iteration erfolgt etwas anders. In Ruby verwenden Sie kein separates Iterator-Objekt (wie
vector<T>::const_iterator iter). Stattdessen verwenden Sie eine Iterator-Methode des Container-Objekts (wieeach), die einen Codeblock entgegennimmt, an den sie nacheinander Elemente übergibt. - Es gibt nur zwei Containertypen:
ArrayundHash. - Es gibt keine Typkonvertierungen. Mit Ruby werden Sie jedoch wahrscheinlich feststellen, dass diese nicht notwendig sind.
- Multithreading ist integriert, aber ab Ruby 1.8 sind es „Green Threads“ (nur innerhalb des Interpreters implementiert) im Gegensatz zu nativen Threads.
- Eine Unit-Testing-Bibliothek wird standardmäßig mit Ruby geliefert.