Stellen Sie sich vor, Sie brauchen eine Möglichkeit, den Wert eines Objekts zu prüfen und darauf basierend eine andere Aktion durchzuführen. Der Weg der objektorientierten Programmierung ist die Verwendung von Polymorphismus, und wir werden gleich sehen, wie man das macht.
Aber zuerst wollen wir uns ansehen, wie der case
-Ausdruck funktioniert und wie Sie ihn verwenden können, um das oben genannte Ziel zu erreichen.
Wie funktioniert Case?
Der case
-Ausdruck besteht aus zwei Hauptteilen. Die case
Klausel und die when
Klausel.
Die when
-Klausel ist der Ausdruck, der den Empfänger des Operators definiert (standardmäßig ===
), und die case
-Klausel definiert das Argument, das an ihn übergeben wird.
Lassen Sie uns ein Beispiel sehen.
case awhen String #..end
So können Sie sich das obige Beispiel als String === a
vorstellen, oder String.===(a)
.
Schließlich gibt es auch eine else
-Klausel, die Sie verwenden können, wenn es keine Übereinstimmung gibt.
case my_objectwhen String "This is a string"else "I have no idea what this is"end
Der dreifache Gleichheitsoperator (===)
Standardmäßig verwendet case
den dreifachen Gleichheitsoperator (===
), um den Vergleich durchzuführen.
Die Sache mit ===
ist, dass es nichts mit Gleichheit zu tun hat. Standardmäßig ist er auf den doppelten Gleichheitsoperator (==
) verlinkt, der normalerweise prüft, ob zwei Objekte den gleichen Wert haben, aber er kann so definiert werden, dass er alles bedeutet.
Ein Bereich definiert ihn zum Beispiel als Alias für includes?
, ein Regex definiert ihn als Alias für match
, eine Klasse für is_a?
, ein Proc für call
. Sie verstehen schon.
Dieser Operator funktioniert wie erwartet mit Literalen, aber nicht mit Klassen:
1 === 1 # => trueNumeric === Numeric # => false
Das liegt daran, dass das ===
ein Alias für kind_of?
ist. Und hier ist die Doku für kind_of?
.
kind_of?(class) → true oder false
Returnt true, wenn class die Klasse von obj ist, oder wenn class eine der Superklassen von obj oder in obj enthaltene Module ist.
Das bedeutet, wenn Sie ein case ... when
über die Klasse eines Objekts machen wollen, funktioniert das nicht:
obj = 'Hi'case obj.classwhen String "It's a string"end
Das liegt daran, dass es zu String === String
übersetzt wird. Und das ergibt false
.
Der Standardoperator
Der Ausdruck case
hat einen Standardoperator. Und das bedeutet, dass Sie ihn nicht angeben müssen. Das ist sehr schön, denn Sie können einfach when String
schreiben und es wird standardmäßig der ===
-Operator verwendet.
Aber es gibt Zeiten, in denen Sie einen anderen Operator verwenden wollen. Und Ruby erlaubt es Ihnen, das zu tun. So geht’s.
casewhen a < 3 "Smaller than 3"end
Case ist ein Ausdruck
Wie der Name schon sagt, ist das Ganze ein Ausdruck. Das heißt, es wird zu einem Wert ausgewertet. Sie können also das Ergebnis des gesamten case
Ausdrucks einer Variablen zuweisen, etwa so.
value = case when a < 3 "Smaller than 3" end
Es gibt kein Durchfallen
Wenn Sie aus anderen Sprachen kommen, haben Sie wahrscheinlich eine switch
-Anweisung oder etwas Ähnliches verwendet, und Sie haben bemerkt, dass case
keine Schlüsselwörter wie break
verwendet, um den Fluss zu unterbrechen.
Das liegt daran, dass es mit case
keinen Durchbruch gibt. Es gibt nur den Wert des Ausdrucks zurück, der übereinstimmt, und das war’s.
Mehrere Übereinstimmungen
Bis jetzt haben Sie nur einen Wert für die when
-Klausel verwendet. Aber Sie können mehrere Werte verwenden.
case awhen 1..3 "Small number"end
Matching regexes
Sie können case
Ausdrücke verwenden, um auf alles zu passen. Aber nur für den Fall, dass es nicht offensichtlich ist, können Sie auch Regexe oder Lambdas abgleichen. Hier ist ein Beispiel.
even = ->(x) { x % 2 == 0 }case awhen even "It's even"when /^+$/ "It's an integer"end
Definieren Sie Ihre eigenen
Eine der weniger bekannten Tatsachen ist, dass Sie Ihre eigenen Komparatoren definieren können.
Text = Struct.new(:min_length) do def ===(string) string.size > min_length && string.is_a?(String) endendcase awhen Text.new(100) "It's text"end
Wenn im obigen Beispiel a
eine Zeichenkette mit mehr als 100 Zeichen ist, dann liefert der case
-Ausdruck It's text
.
Verwenden Sie stattdessen Polymorphismus
Ich werde hier nicht auf die Vorteile von OOP eingehen, Sie können mehr darüber im Artikel Objektorientierte Programmierung mit Ruby lesen, aber ich werde Ihnen zeigen, wie Sie Polymorphismus verwenden können, um einen case
-Ausdruck zu ersetzen.
Die Case-Version
class Person attr_reader :country def initialize(country) @country = country end def nationality case country when "USA" "This guy is an American" when "Romania" "This guy is a Romanian" end endendjohn = Person.new("USA")puts john.nationality # => This guy is an American
Die OOP-Version
class Person attr_reader :country def initialize(country) @country = country end def nationality country.nationality endendclass America def nationality "This guy is an American" endendclass Romania def nationality "This guy is a Romanian" endendjohn = Person.new(America.new)puts john.nationality # => This guy is an American
Es ist eine gute Idee, so viel Flusskontrollcode (d.d. h. if
s, und case
-Ausdrücke) wie möglich zu entfernen. Es verbessert die Einhaltung des Single-Responsibility-Prinzips und macht das Programm insgesamt lesbarer.