Module in Crystal erfüllen zwei Zwecke:
Der erste Zweck ist, einen Namensraum zu schaffen, um Namenskollisionen zu vermeiden. Er gruppiert aber auch Code, was verständlicher macht, wofür der Code gedacht ist.
Der zweite Zweck ist, Mixins zu definieren, um Code mit Typen zu teilen.
Module ähneln Klassen, aber der Hauptunterschied ist, dass sie nicht instanziiert werden können und daher keine Instanzvariablen haben.
Um ein Modul zu deklarieren, verwendest du das Schlüsselwort module, gefolgt vom Namen des Moduls.
module Foo
end
Ein Namensraum ist eine Möglichkeit, Code zu gruppieren.
Das vermeidet Namenskonflikte und macht verständlicher, wofür der Code gedacht ist.
Wenn du auf eine Konstante oder eine Klasse zugreifen willst, die in einem Namensraum liegt, verwendest du den Operator ::.
module Foo
class Bar
end
end
Foo::Bar.new
Das kann nützlich sein, wenn zum Beispiel mehrere Klassen dieselbe „Basis“-Funktionalität brauchen oder wenn Code zwischen nicht verwandten Klassen geteilt werden soll. Oder wenn du Code zwischen Klassen teilen willst, die nichts miteinander zu tun haben.
Es gibt zwei verschiedene Möglichkeiten, ein Modul als Mixin zu verwenden: Die erste verwendet das Schlüsselwort include, die zweite das Schlüsselwort extend.
Beide Methoden machen Konstanten für den Typ verfügbar, der das Modul einbindet oder erweitert.
Include macht alle Methoden im Modul als Instanzmethoden auf dem Typ verfügbar, der das Modul einbindet.
Das Schlüsselwort include gehört an den Anfang des Typs, gefolgt vom Namen des Moduls.
module Foo
def foo
"foo"
end
end
class Bar
include Foo
end
Bar.new.foo # => "foo"
Extend funktioniert ähnlich wie Include, aber statt die Methoden als Instanzmethoden verfügbar zu machen, macht es sie als Klassenmethoden verfügbar.
Das Schlüsselwort extend gehört an den Anfang des Typs, gefolgt vom Namen des Moduls.
module Foo
def foo
"foo"
end
end
class Bar
extend Foo
end
Bar.foo # => "foo"
Ein typisches Muster in Crystal verwendet das Muster extend self in einem Modul.
Dadurch werden alle Methoden im Modul als Klassenmethoden auf dem Modul selbst verfügbar.
Das heißt, du musst nicht jede Methode mit der Syntax def self.method_name dem Modul zuweisen.
module Foo
extend self
def foo
"foo"
end
end
Foo.foo # => "foo"
Die Bellebrook Basketball League ist eine Liga aus mehreren Teams, die jeweils einen Kader von Spielern haben. Eine neue Saison steht kurz bevor, und die Liga braucht ein neues Ticketsystem, um Tickets für die Spiele zu verkaufen. In der letzten Saison wurden die Tickets am Stadioneingang verkauft, doch die Beliebtheit ist explodiert, und deshalb hat sich die Liga entschieden, die Tickets in dieser Saison online zu verkaufen, um die gestiegene Nachfrage zu bewältigen.
Die Liga hat sich an dich gewandt und dich gebeten, ein System für den Ticketverkauf zu erstellen.
Zuerst musst du ein Ticketsystem erstellen, das den Ticketverkauf abwickelt. Das Ticketsystem muss angeben, wie viele Tickets für ein Spiel verfügbar sind.
Für jedes Spiel soll eine Instanz einer Klasse namens TicketSystem erstellt werden.
Der initialisierte Zustand soll die folgenden Informationen enthalten:
Erzeuge den initialisierten Zustand aus Argumenten, die angeben, wie viele Tickets verfügbar sind und in welchem Stadion das Spiel ausgetragen wird.
Der initialisierte Zustand soll aus den Instanzvariablen @tickets_available und @stadium bestehen.
Diese sollen das erste bzw. das zweite übergebene Argument enthalten.
TicketSystem.new(100, "Bellebrook")
# => #<TicketSystem:0x10f0b8 @tickets_available=100, @stadium="Bellebrook">
Zuerst musst du eine Methode erstellen, die die Anzahl der für ein bestimmtes Spiel verfügbaren Tickets zurückgibt.
Definiere ein Modul namens TicketingReservation oberhalb der bereits definierten Klasse.
Dieses Modul soll in die Klasse TicketSystem eingebunden werden.
Definiere im Modul eine Methode namens tickets_available.
Diese Methode soll die Anzahl der verfügbaren Tickets zurückgeben.
ticket_system = TicketSystem.new(100)
ticket_system.tickets_available
#=> 100
Du musst eine Methode erstellen, die prüft, ob für ein bestimmtes Spiel Tickets verfügbar sind. Für das Spiel müssen 100 Tickets in Reserve bleiben. So soll sichergestellt werden, dass immer Tickets für die Leute verfügbar sind, die ihre Tickets am Stadioneingang kaufen.
Definiere im Modul TicketingReservation eine Methode namens order_ticket?.
Die Methode soll true zurückgeben, wenn mindestens 100 Tickets verfügbar sind, andernfalls false.
Wenn mindestens 100 Tickets verfügbar sind, soll die Methode außerdem die Anzahl der verfügbaren Tickets um 1 verringern.
ticket_system = TicketSystem.new(100)
ticket_system.order_ticket?
#=> true
Das Ticketsystem muss Nachrichten haben, die für Nutzer leicht zu verstehen sind. Und die Nachrichten sollen persönlich wirken, also den Namen des Nutzers enthalten.
Wenn der Ticketkauf erfolgreich war, soll der Nutzer eine Nachricht erhalten, die ihm sagt, dass der Kauf erfolgreich war, wie seine Ticketnummer lautet und in welchem Stadion das Spiel ausgetragen wird. Die Ticketnummer soll die Anzahl der Tickets sein, die vor der Bestellung verfügbar waren.
Wenn der Kauf erfolgreich war, soll die Nachricht so aussehen: {name}, your purchase was successful, your ticket number is #{ticket_number}, and the game is played at the {stadium_name} stadium..
Wenn der Kauf nicht erfolgreich war, soll die Nachricht so aussehen: {name}, your purchase was unsuccessful, there are not enough tickets available..
Definiere im Modul TicketingReservation, eine Methode namens order_message, die ein Argument name entgegennimmt, das den Namen des Käufers enthält.
Die Methode soll einen String mit der Nachricht zurückgeben.
ticket_system = TicketSystem.new(100, "Bellebrook")
ticket_system.order_message("John")
#=> "John, your purchase was successful, your ticket number is #100, and the game is played at the Bellebrook stadium."
Melde dich bei Exercism an, um Crystal mit 26 Konzepte142 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.