Οι ενότητες στη Crystal εξυπηρετούν δύο σκοπούς:
Ο πρώτος σκοπός είναι να δημιουργούν έναν χώρο ονομάτων για να αποφεύγονται οι συγκρούσεις ονομάτων. Ωστόσο, ομαδοποιούν και τον κώδικα, κάνοντας πιο εύκολο να καταλάβεις για τι χρησιμεύει ο κώδικας.
Ο δεύτερος σκοπός είναι να ορίζουν mixin για να μοιράζουν κώδικα σε τύπους.
Οι ενότητες μοιάζουν με τις κλάσεις, αλλά η βασική διαφορά είναι ότι δε μπορούν να δημιουργηθούν στιγμιότυπα και, επομένως, δεν έχουν μεταβλητές στιγμιότυπου.
Για να δηλώσεις μια ενότητα, χρησιμοποιείς τη λέξη-κλειδί module ακολουθούμενη από το όνομα της ενότητας.
module Foo
end
Ένας χώρος ονομάτων είναι ένας τρόπος να ομαδοποιείς κώδικα.
Έτσι αποφεύγονται οι συγκρούσεις ονομάτων και γίνεται πιο εύκολο να καταλάβεις για τι χρησιμεύει ο κώδικας.
Όταν θέλεις να προσπελάσεις μια σταθερά ή μια κλάση που έχει τοποθετηθεί μέσα σε έναν χώρο ονομάτων, χρησιμοποιείς τον τελεστή ::.
module Foo
class Bar
end
end
Foo::Bar.new
Αυτό μπορεί να είναι χρήσιμο όταν, για παράδειγμα, πολλές κλάσεις χρειάζονται την ίδια λειτουργικότητα "βάσης" ή όταν ο κώδικας πρέπει να μοιράζεται μεταξύ άσχετων κλάσεων. Ή όταν θέλεις να μοιραστείς κώδικα μεταξύ κλάσεων που δε σχετίζονται.
Υπάρχουν δύο διαφορετικοί τρόποι να χρησιμοποιήσεις μια ενότητα ως mixin: ο πρώτος είναι να χρησιμοποιήσεις τη λέξη-κλειδί include και ο δεύτερος είναι να χρησιμοποιήσεις τη λέξη-κλειδί extend.
Και οι δύο μέθοδοι κάνουν τις σταθερές διαθέσιμες στον τύπο που συμπεριλαμβάνει ή επεκτείνει την ενότητα.
Με το Include, όλες οι μέθοδοι της ενότητας γίνονται διαθέσιμες ως μέθοδοι στιγμιότυπου στον τύπο που συμπεριλαμβάνει την ενότητα.
Η λέξη-κλειδί include πρέπει να βρίσκεται στην κορυφή του τύπου, ακολουθούμενη από το όνομα της ενότητας.
module Foo
def foo
"foo"
end
end
class Bar
include Foo
end
Bar.new.foo # => "foo"
Το Extend λειτουργεί παρόμοια με το Include, αλλά αντί να κάνει τις μεθόδους διαθέσιμες ως μεθόδους στιγμιότυπου, τις κάνει διαθέσιμες ως μεθόδους κλάσης.
Η λέξη-κλειδί extend πρέπει να γραφτεί στην κορυφή του τύπου, ακολουθούμενη από το όνομα της ενότητας.
module Foo
def foo
"foo"
end
end
class Bar
extend Foo
end
Bar.foo # => "foo"
Ένα τυπικό μοτίβο στη Crystal χρησιμοποιεί το μοτίβο extend self σε μια ενότητα.
Έτσι, όλες οι μέθοδοι της ενότητας γίνονται διαθέσιμες ως μέθοδοι κλάσης στην ίδια την ενότητα.
Αυτό σημαίνει ότι δε χρειάζεται να αναθέσεις κάθε μέθοδο στην ενότητα χρησιμοποιώντας τη σύνταξη def self.method_name.
module Foo
extend self
def foo
"foo"
end
end
Foo.foo # => "foo"
Η Bellebrook Basketball League είναι μια λίγκα με πολλές ομάδες, καθεμία με το ρόστερ των παικτών της. Μια νέα σεζόν πρόκειται να ξεκινήσει και χρειάζονται ένα νέο σύστημα έκδοσης εισιτηρίων για να πουλάνε εισιτήρια για τους αγώνες. Την περασμένη σεζόν πουλούσαν τα εισιτήρια στην είσοδο του σταδίου, αλλά η δημοτικότητα εκτοξεύτηκε και αποφάσισαν να πουλάνε τα εισιτήρια online αυτή τη σεζόν, για να ανταπεξέλθουν στην αυξημένη ζήτηση.
Η λίγκα επικοινώνησε μαζί σου και σου ζήτησε να δημιουργήσεις ένα σύστημα για να διαχειρίζεσαι τις πωλήσεις εισιτηρίων.
Πρώτα, χρειάζεται να δημιουργήσεις ένα σύστημα έκδοσης εισιτηρίων για να διαχειρίζεσαι τις πωλήσεις εισιτηρίων. Το σύστημα έκδοσης εισιτηρίων πρέπει να λέει πόσα εισιτήρια είναι διαθέσιμα για έναν αγώνα.
Για κάθε αγώνα πρέπει να δημιουργείται ένα στιγμιότυπο μιας κλάσης με το όνομα TicketSystem.
Η αρχική κατάσταση πρέπει να περιέχει τις εξής πληροφορίες:
Κατασκεύασε μια αρχική κατάσταση από ορίσματα που δηλώνουν τον αριθμό των διαθέσιμων εισιτηρίων και σε ποιο στάδιο παίζεται ο αγώνας.
Η αρχική κατάσταση πρέπει να αποτελείται από τις μεταβλητές στιγμιοτύπου @tickets_available και @stadium.
Αυτές πρέπει να περιέχουν το πρώτο και το δεύτερο όρισμα που δίνονται, αντίστοιχα.
TicketSystem.new(100, "Bellebrook")
# => #<TicketSystem:0x10f0b8 @tickets_available=100, @stadium="Bellebrook">
Πρώτα, χρειάζεται να δημιουργήσεις μια μέθοδο που επιστρέφει τον αριθμό των διαθέσιμων εισιτηρίων για έναν δεδομένο αγώνα.
Όρισε ένα module με το όνομα TicketingReservation πάνω από την κλάση που έχεις ήδη ορίσει.
Αυτό το module πρέπει να συμπεριληφθεί στην κλάση TicketSystem.
Μέσα στο module, όρισε μια μέθοδο με το όνομα tickets_available.
Αυτή η μέθοδος πρέπει να επιστρέφει τον αριθμό των διαθέσιμων εισιτηρίων.
ticket_system = TicketSystem.new(100)
ticket_system.tickets_available
#=> 100
Πρέπει να δημιουργήσεις μια μέθοδο που ελέγχει αν υπάρχουν διαθέσιμα εισιτήρια για έναν δεδομένο αγώνα. Ο αγώνας πρέπει να έχει 100 εισιτήρια σε αποθεματικό. Αυτό γίνεται για να διασφαλιστεί ότι υπάρχουν πάντα διαθέσιμα εισιτήρια για όσους αγοράζουν εισιτήρια στην είσοδο του σταδίου.
Μέσα στο module TicketingReservation, όρισε μια μέθοδο με το όνομα order_ticket?.
Η μέθοδος πρέπει να επιστρέφει true αν υπάρχουν τουλάχιστον 100 διαθέσιμα εισιτήρια και false διαφορετικά.
Αν υπάρχουν τουλάχιστον 100 διαθέσιμα εισιτήρια, η μέθοδος πρέπει επίσης να μειώνει τον αριθμό των διαθέσιμων εισιτηρίων κατά 1.
ticket_system = TicketSystem.new(100)
ticket_system.order_ticket?
#=> true
Το σύστημα έκδοσης εισιτηρίων πρέπει να έχει μηνύματα που οι χρήστες καταλαβαίνουν εύκολα. Και τα μηνύματα πρέπει να είναι προσωπικά, οπότε πρέπει να περιλαμβάνουν το όνομα του χρήστη.
Αν η αγορά του εισιτηρίου ήταν επιτυχής, ο χρήστης πρέπει να λαμβάνει ένα μήνυμα που του λέει ότι η αγορά ήταν επιτυχής, ποιος είναι ο αριθμός του εισιτηρίου του και σε ποιο στάδιο παίζεται ο αγώνας. Ο αριθμός του εισιτηρίου πρέπει να είναι ο αριθμός των διαθέσιμων εισιτηρίων πριν από την παραγγελία.
Αν η αγορά ήταν επιτυχής, το μήνυμα πρέπει να μοιάζει με αυτό: {name}, your purchase was successful, your ticket number is #{ticket_number}, and the game is played at the {stadium_name} stadium..
Αν η αγορά δεν ήταν επιτυχής, το μήνυμα πρέπει να μοιάζει με αυτό: {name}, your purchase was unsuccessful, there are not enough tickets available..
Μέσα στο module TicketingReservation, όρισε μια μέθοδο με το όνομα order_message που παίρνει ένα όρισμα name που περιέχει το όνομα του αγοραστή.
Η μέθοδος πρέπει να επιστρέφει μια συμβολοσειρά με το μήνυμα.
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."
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Crystal με 26 έννοιες142 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.