05. Mehr über Methoden
Bisher haben wir eine Reihe verschiedener Methoden gesehen, puts und gets unter anderem (Pop-Quiz: Listen Sie alle Methoden auf, die wir bisher gesehen haben! Es waren zehn; die Antwort steht weiter unten.), aber wir haben nicht wirklich darüber gesprochen, was Methoden sind. Wir wissen, was sie tun, aber wir wissen nicht, was sie sind.
Aber eigentlich ist es genau das, was sie sind: Dinge, die Dinge tun. Wenn Objekte (wie Strings, Integer und Floats) die Substantive in der Sprache Ruby sind, dann sind Methoden wie die Verben. Und anders als im Deutschen (wo es unbestimmte Subjekte und andere esoterische Konstruktionen gibt), kann man kein Verb ohne ein Substantiv haben, das das Verb ausführt. Aber selbst das Deutsche behandelt das Fehlen eines Substantivs als Ausnahme: Zum Beispiel passiert Ticken nicht einfach so; eine Uhr (oder eine Stoppuhr oder etwas Ähnliches) muss es tun. Im Deutschen würden wir sagen: "Die Uhr tickt." In Ruby sagen wir uhr.ticken (vorausgesetzt, uhr ist ein Ruby-Objekt, natürlich). Programmierer könnten sagen, dass wir "die Methode ticken auf uhr aufrufen" oder dass wir "ticken auf uhr aufgerufen haben".
Also, haben Sie das Quiz gemacht? Gut. Nun, ich bin sicher, Sie haben sich an die Methoden puts, gets und chomp erinnert, die wir gerade gesehen haben. Sie haben sich wahrscheinlich auch an die Konvertierungsmethoden to_i, to_f und to_s erinnert. Haben Sie jedoch die anderen vier bekommen? Nun, sie waren keine anderen als unsere alten Rechenfreunde +, -, * und /!
Wie ich schon sagte, jede Methode braucht ein Objekt. Normalerweise ist es einfach zu sagen, welches Objekt die Methode ausführt: Es ist das, was direkt vor dem Punkt kommt, wie in unserem Beispiel uhr.ticken oder in 101.to_s. Manchmal ist es jedoch nicht so offensichtlich; wie bei den arithmetischen Methoden. Tatsächlich ist 5 + 5 eigentlich nur eine Abkürzung für 5.+ 5. Zum Beispiel:
puts 'hallo '.+ 'welt'
puts (10.* 9).+ 9
hallo welt
99
Es ist nicht sehr hübsch, also werden wir es nie so schreiben; es ist jedoch wichtig zu verstehen, was wirklich passiert. (Auf meinem Rechner gibt mir das auch eine Warnung: warning: parenthesize argument(s) for future version. Der Code lief trotzdem gut, aber er sagt mir, dass er Probleme hat herauszufinden, was ich gemeint habe, und bittet mich, in Zukunft mehr Klammern zu verwenden). Dies gibt uns auch ein tieferes Verständnis dafür, warum wir 'schwein'*5 machen können, aber nicht 5*'schwein': 'schwein'*5 sagt dem 'schwein', dass es die Multiplikation durchführen soll, aber 5*'schwein' bittet die 5, die Multiplikation durchzuführen. 'schwein' weiß, wie es 5 Kopien von sich selbst erstellt und zusammenfügt; 5 wird es jedoch viel schwerer haben, 'schwein' Kopien von sich selbst zu erstellen und zusammenzufügen.
Und natürlich haben wir noch puts und gets zu erklären. Wo sind ihre Objekte? Im Deutschen kann man das Substantiv manchmal weglassen; zum Beispiel, wenn ein Bösewicht schreit "Stirb!", ist das implizite Substantiv die Person, die er anschreit. In Ruby, wenn ich sage puts 'sein oder nicht sein', sage ich eigentlich self.puts 'sein oder nicht sein'. Also was ist self? Es ist eine spezielle Variable, die auf das Objekt zeigt, in dem Sie sich gerade befinden. Wir wissen noch nicht einmal, wie man in einem Objekt ist, aber bis wir es herausfinden, sind wir immer in einem großen Objekt, das... das ganze Programm ist! Und wie das Glück so spielt, hat das Programm ein paar eigene Methoden, wie puts und gets. Schauen Sie sich das an:
ichKannNichtGlaubenDassIchEinenSoLangenVariablennamenGemachtHabeNurUmEine3ZuSpeichern = 3
puts ichKannNichtGlaubenDassIchEinenSoLangenVariablennamenGemachtHabeNurUmEine3ZuSpeichern
self.puts ichKannNichtGlaubenDassIchEinenSoLangenVariablennamenGemachtHabeNurUmEine3ZuSpeichern
3
3
Wenn Sie dem nicht ganz folgen konnten, ist das in Ordnung. Das Wichtige, was Sie daraus mitnehmen sollten, ist, dass jede Methode von einem Objekt ausgeführt wird, auch wenn es nicht direkt vor Ihnen liegt. Wenn Sie das verstehen, dann sind Sie bereit.
Schicke String-Methoden
Lassen Sie uns ein paar lustige String-Methoden lernen. Sie müssen sie nicht alle auswendig lernen; Sie können einfach wieder auf diese Seite schauen, wenn Sie sie vergessen. Ich möchte Ihnen nur einen kleinen Teil dessen zeigen, was Strings tun können. Tatsächlich erinnere ich mich selbst nicht einmal an die Hälfte der String-Methoden – aber das ist in Ordnung, denn es gibt großartige Referenzen im Internet, in denen alle String-Methoden aufgelistet und erklärt sind. (Ich werde Ihnen am Ende dieses Tutorials zeigen, wo Sie sie finden.) Um ehrlich zu sein, ich will gar nicht alle String-Methoden kennen; es ist, als würde man jedes Wort im Wörterbuch kennen. Ich kann perfekt Deutsch sprechen, ohne jedes Wort im Wörterbuch zu kennen... und ist das nicht der springende Punkt? Dass man nicht alles wissen muss, was darin steht?
Also, unsere erste String-Methode ist reverse, die uns eine rückwärts gerichtete Version des Strings gibt:
var1 = 'stop'
var2 = 'radar'
var3 = 'Kannst du diesen Satz ruckwarts aussprechen?'
puts var1.reverse
puts var2.reverse
puts var3.reverse
puts var1
puts var2
puts var3
pots
radar
?nehcerpssua strawkcur ztaS neseid ud tsnnaK
stop
radar
Kannst du diesen Satz ruckwarts aussprechen?
Wie Sie sehen können, kehrt reverse den ursprünglichen String nicht um; es erstellt nur eine neue rückwärts gerichtete Version davon. Deshalb ist var1 immer noch 'stop', auch nachdem wir reverse auf var1 aufgerufen haben.
Eine weitere String-Methode ist length, die uns die Anzahl der Zeichen (einschließlich Leerzeichen) im String angibt:
puts 'Wie ist Ihr vollstandiger Name?'
name = gets.chomp
puts 'Wussten Sie, dass Ihr Name ' + name.length + ' Zeichen hat, ' + name + '?'
Wie ist Ihr vollstandiger Name?
Christopher David Pine
#<TypeError: can't convert Fixnum into String>
Uh-oh! Etwas ist schief gelaufen, und es sieht so aus, als wäre es nach der Zeile name = gets.chomp passiert... Sehen Sie das Problem? Versuchen Sie, es herauszufinden.
Das Problem liegt bei length: Es gibt Ihnen eine Zahl, aber wir wollen einen String. Einfach genug, werfen wir ein to_s hinein (und drücken die Daumen):
puts 'Wie ist Ihr vollstandiger Name?'
name = gets.chomp
puts 'Wussten Sie, dass Ihr Name ' + name.length.to_s + ' Zeichen hat, ' + name + '?'
Wie ist Ihr vollstandiger Name?
Christopher David Pine
Wussten Sie, dass Ihr Name 22 Zeichen hat, Christopher David Pine?
Nein, das wusste ich nicht. Hinweis: Dies ist die Anzahl der Zeichen in meinem Namen, nicht die Anzahl der Buchstaben (zählen Sie sie). Ich schätze, wir könnten ein Programm schreiben, das einzeln nach Ihrem Vor-, Mittel- und Nachnamen fragt und dann diese Längen addiert... Hey, warum machen Sie das nicht? Nur zu, ich warte.
Bereit? Gut! Es ist ein schönes Programm, nicht wahr? Nach ein paar weiteren Kapiteln werden Sie jedoch erstaunt sein, was Sie tun können.
Es gibt auch eine Reihe von String-Methoden, die die Groß-/Kleinschreibung Ihres Strings ändern. upcase ändert jeden Kleinbuchstaben in einen Großbuchstaben, und downcase ändert jeden Großbuchstaben in einen Kleinbuchstaben. swapcase wechselt die Groß-/Kleinschreibung jedes Buchstabens im String, und schließlich ist capitalize genau wie downcase, außer dass es das erste Zeichen in einen Großbuchstaben ändert (wenn es ein Buchstabe ist).
buchstaben = 'aAbBcCdDeE'
puts buchstaben.upcase
puts buchstaben.downcase
puts buchstaben.swapcase
puts buchstaben.capitalize
puts ' a'.capitalize
puts buchstaben
AABBCCDDEE
aabbccddee
AaBbCcDdEe
Aabbccddee
a
aAbBcCdDeE
Ziemlich standardmäßiges Zeug. Wie Sie aus der Zeile puts ' a'.capitalize sehen können, schreibt die Methode capitalize nur das erste Zeichen groß, nicht den ersten Buchstaben. Auch, wie wir zuvor gesehen haben, bleibt buchstaben während all dieser Methodenaufrufe unverändert. Ich will nicht darauf herumreiten, aber es ist wichtig zu verstehen. Es gibt einige Methoden, die das zugehörige Objekt ändern, aber wir haben noch keine gesehen, und das werden wir auch eine Weile nicht.
Die letzten der schicken String-Methoden, die wir uns ansehen werden, dienen der visuellen Formatierung. Die erste, center, fügt Leerzeichen am Anfang und Ende des Strings hinzu, um ihn zu zentrieren. Genauso wie Sie puts sagen müssen, was es drucken soll, und +, was es addieren soll, müssen Sie center sagen, wie breit Ihr zentrierter String sein soll. Wenn ich also die Zeilen eines Gedichts zentrieren wollte, würde ich das so machen:
zeilenbreite = 50
puts( 'Old Mother Hubbard'.center(zeilenbreite))
puts( 'Sat in her cupboard'.center(zeilenbreite))
puts( 'Eating her curds an whey,'.center(zeilenbreite))
puts( 'When along came a spider'.center(zeilenbreite))
puts( 'Which sat down beside her'.center(zeilenbreite))
puts('And scared her poor shoe dog away.'.center(zeilenbreite))
Old Mother Hubbard
Sat in her cupboard
Eating her curds an whey,
When along came a spider
Which sat down beside her
And scared her poor shoe dog away.
Hmm... Ich glaube nicht, dass der Kinderreim so geht, aber ich bin zu faul, um nachzuschlagen. (Außerdem wollte ich den Teil .center zeilenbreite ausrichten, also habe ich diese zusätzlichen Leerzeichen vor die Strings gesetzt. Das liegt nur daran, dass ich denke, dass es hübscher aussieht. Programmierer haben oft starke Gefühle darüber, was in einem Programm hübsch ist, und sie sind sich oft nicht einig. Je mehr Sie programmieren, desto mehr werden Sie Ihren eigenen Stil entwickeln). Apropos faul sein, Faulheit ist beim Programmieren nicht immer eine schlechte Sache. Haben Sie zum Beispiel gesehen, wie ich die Breite des Gedichts in der Variablen zeilenbreite gespeichert habe? Ich habe das getan, damit ich, wenn ich das Gedicht später breiter machen möchte, nur die allererste Zeile des Programms ändern muss, anstatt jede Zeile, die die Zentrierung durchführt. Bei einem sehr langen Gedicht könnte mir das viel Zeit sparen. Diese Art von Faulheit ist wirklich eine Tugend beim Programmieren.
Also, über dieses Zentrieren... Sie haben vielleicht bemerkt, dass es nicht ganz so schön ist, wie es ein Textverarbeitungsprogramm getan hätte. Wenn Sie wirklich eine perfekte Zentrierung (und vielleicht eine schönere Schriftart) wollen, dann sollten Sie einfach ein Textverarbeitungsprogramm verwenden! Ruby ist ein wunderbares Werkzeug, aber kein Werkzeug ist das richtige Werkzeug für jede Arbeit.
Die anderen beiden String-Formatierungsmethoden sind ljust und rjust, was für linksbündig und rechtsbündig steht. Sie ähneln center, außer dass sie den String mit Leerzeichen auf der rechten bzw. linken Seite auffüllen. Sehen wir uns alle drei in Aktion an:
zeilenbreite = 40
str = '--> text <--'
puts str.ljust zeilenbreite
puts str.center zeilenbreite
puts str.rjust zeilenbreite
puts str.ljust (zeilenbreite/2) + str.rjust (zeilenbreite/2)
--> text <--
--> text <--
--> text <--
--> text <-- --> text <--
Ein paar Dinge zum Ausprobieren
- Schreiben Sie ein Wütender Boss-Programm. Es sollte unhöflich fragen, was Sie wollen. Was auch immer Sie antworten, der wütende Boss sollte es Ihnen zurückschreien und Sie dann feuern. Wenn Sie zum Beispiel
Ich will eine Gehaltserhöhung.eingeben, sollte er zurückschreienWAS MEINST DU MIT "ICH WILL EINE GEHALTSERHÖHUNG."?!? DU BIST GEFEUERT!! - Hier ist etwas für Sie, um mehr mit
center,ljustundrjustherumzuspielen: Schreiben Sie ein Programm, das ein Inhaltsverzeichnis anzeigt, sodass es so aussieht:
Inhaltsverzeichnis
Kapitel 1: Zahlen Seite 1
Kapitel 2: Buchstaben Seite 72
Kapitel 3: Variablen Seite 118
Höhere Mathematik
(Dieser Abschnitt ist völlig optional. Er setzt ein gewisses Maß an mathematischen Kenntnissen voraus. Wenn Sie nicht interessiert sind, können Sie ohne Probleme direkt zur Flusskontrolle gehen. Ein kurzer Blick auf den Abschnitt Zufallszahlen könnte jedoch nützlich sein.)
Es gibt bei weitem nicht so viele Zahlenmethoden wie String-Methoden (obwohl ich immer noch nicht alle auswendig gelernt habe). Hier werden wir uns den Rest der arithmetischen Methoden, einen Zufallszahlengenerator und das Math-Objekt mit seinen trigonometrischen und transzendentalen Methoden ansehen.
Mehr Arithmetik
Die anderen beiden arithmetischen Methoden sind ** (Potenzierung) und % (Modulus). Wenn Sie also in Ruby "fünf zum Quadrat" sagen wollten, würden Sie 5**2 schreiben. Sie können auch Floats für Ihren Exponenten verwenden, wenn Sie also die Quadratwurzel von 5 wollen, können Sie 5**0.5 schreiben. Die Modulus-Methode gibt Ihnen den Rest nach der Division durch eine Zahl. Wenn ich also zum Beispiel 7 durch 3 teile, erhalte ich 2 mit einem Rest von 1. Sehen wir sie uns in einem Programm in Aktion an:
puts 5**2
puts 5**0.5
puts 7/3
puts 7%3
puts 365%7
25
2.23606797749979
2
1
1
Aus dieser letzten Zeile lernen wir, dass ein (Nicht-Schalt-)Jahr eine bestimmte Anzahl von Wochen plus einen Tag hat. Wenn Ihr Geburtstag dieses Jahr also an einem Dienstag war, wird er nächstes Jahr an einem Mittwoch sein. Sie können auch Floats mit der Modulus-Methode verwenden. Es funktioniert im Grunde auf die einzig vernünftige Weise, wie es kann... aber ich lasse Sie damit herumspielen.
Es gibt eine letzte Methode zu erwähnen, bevor wir uns den Zufallszahlengenerator ansehen: abs. Sie nimmt einfach den absoluten Wert der Zahl:
puts((5-2).abs)
puts((2-5).abs)
3
3
Zufallszahlen
Ruby kommt mit einem ziemlich netten Zufallszahlengenerator. Die Methode, um eine zufällig ausgewählte Zahl zu erhalten, ist rand. Wenn Sie rand einfach so aufrufen, erhalten Sie einen Float größer oder gleich 0.0 und kleiner als 1.0. Wenn Sie rand eine Ganzzahl geben (zum Beispiel 5), erhalten Sie eine Ganzzahl größer oder gleich 0 und kleiner als 5 (also fünf mögliche Zahlen, von 0 bis 4).
Sehen wir uns rand in Aktion an. (Wenn Sie diese Seite neu laden, ändern sich diese Zahlen jedes Mal. Sie wussten, dass ich diese Programme tatsächlich ausführe, oder?)
puts rand
puts rand
puts rand
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(1))
puts(rand(1))
puts(rand(1))
puts(rand(99999999999999999999999999999999999999999999999999999999999))
puts('Der Wetterbericht sagte, es gibt eine '+rand(101).to_s+'% Chance auf Regen,')
puts('aber man kann einem Wetterbericht nie trauen.')
0.533099438199271
0.692927743758217
0.940976910494312
35
25
43
0
0
0
43268570703742641064840128301077341089498686011220522458380
Der Wetterbericht sagte, es gibt eine 42% Chance auf Regen,
aber man kann einem Wetterbericht nie trauen.
Beachten Sie, dass ich rand(101) verwendet habe, um Zahlen von 0 bis 100 zu erhalten, und dass rand(1) immer 0 zurückgibt. Das Nichtverstehen des Bereichs möglicher Rückgabewerte ist der größte Fehler, den ich Leute bei rand machen sehe; sogar professionelle Programmierer; sogar in fertigen Produkten, die man im Laden kaufen kann. Ich hatte einmal einen CD-Player, der, wenn er auf "Zufallswiedergabe" eingestellt war, jedes Lied außer dem letzten abspielte... (Ich frage mich, was passieren würde, wenn man eine CD mit nur einem Lied darauf einlegte?)
Manchmal möchten Sie vielleicht, dass rand dieselben Zufallszahlen in derselben Reihenfolge bei zwei verschiedenen Ausführungen Ihres Programms zurückgibt. (Zum Beispiel habe ich einmal Zufallszahlen verwendet, um eine zufällig generierte Welt in einem Computerspiel zu erstellen. Wenn ich eine Welt fand, die mir wirklich gefiel, wollte ich sie vielleicht noch einmal spielen oder an einen Freund senden). Um dies zu tun, müssen Sie den Seed (Samen) setzen, was Sie mit srand tun können. So:
srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts ''
srand 1776
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
puts(rand(100))
24
35
36
58
70
24
35
36
58
70
Es wird jedes Mal dasselbe tun, wenn Sie es mit derselben Zahl säen. Wenn Sie wieder verschiedene Zahlen erhalten möchten (wie es passiert, wenn Sie srand nie treffen), dann rufen Sie einfach srand 0 auf. Dies sät es mit einer wirklich seltsamen Zahl, unter Verwendung (unter anderem) der aktuellen Zeit auf Ihrem Computer, bis auf die Millisekunde genau.
Das Math-Objekt
Schließlich schauen wir uns das Math-Objekt an. Lassen Sie uns einfach direkt hineinspringen:
puts(Math::PI)
puts(Math::E)
puts(Math.cos(Math::PI/3))
puts(Math.tan(Math::PI/4))
puts(Math.log(Math::E**2))
puts((1 + Math.sqrt(5))/2)
3.14159265358979
2.71828182845905
0.5
1.0
2.0
1.61803398874989
Das Erste, was Ihnen aufgefallen ist, war wahrscheinlich die ::-Notation. Den Bereichsoperator zu erklären (was das ist), liegt ein wenig außerhalb des, äh... Bereichs dieses Tutorials. Kein Wortspiel beabsichtigt. Ich schwöre. Es genügt zu sagen, dass Sie Math::PI genau so verwenden können, wie Sie es erwarten.
Wie Sie sehen können, hat Math alle Dinge, die Sie von einem anständigen wissenschaftlichen Taschenrechner erwarten würden. Und wie immer sind die Floats wirklich nah dran, die richtigen Antworten zu sein.
Also lassen Sie uns in den Fluss kommen!