Συχνά είναι χρήσιμο να ομαδοποιείς μια συλλογή από στοιχεία και να χειρίζεσαι αυτές τις ομάδες ως μονάδες. Στη Cairo, μια τέτοια ομάδα την ονομάζουμε struct, και κάθε στοιχείο της είναι ένα από τα πεδία του struct. Ένα struct ορίζει το γενικό σύνολο των διαθέσιμων πεδίων, αλλά ένα συγκεκριμένο παράδειγμα ενός struct ονομάζεται στιγμιότυπο.
Επιπλέον, τα structs μπορούν να έχουν μεθόδους ορισμένες πάνω τους, οι οποίες έχουν πρόσβαση στα πεδία.
Το ίδιο το struct σε αυτή την περίπτωση αναφέρεται ως self.
Όταν μια μέθοδος χρησιμοποιεί ref self: SomeStruct, τα πεδία μπορούν να αλλάξουν, ή να μεταβληθούν.
Όταν μια μέθοδος χρησιμοποιεί self: SomeStruct ή self: @SomeStruct, τα πεδία δεν μπορούν να αλλάξουν: είναι αμετάβλητα.
Ο έλεγχος της μεταβλητότητας βοηθά τον borrow-checker να διασφαλίσει ότι ολόκληρες κατηγορίες από bugs ταυτοχρονισμού απλώς δε συμβαίνουν στη Cairo.
Σε αυτή την άσκηση, θα υλοποιήσεις δύο είδη μεθόδων σε ένα struct. Τα πρώτα είναι γενικά γνωστά ως getters: εκθέτουν τα πεδία του struct στον έξω κόσμο, χωρίς να αφήνουν κανέναν άλλο να μεταβάλει αυτή την τιμή.
Θα υλοποιήσεις επίσης μεθόδους ενός άλλου τύπου, γενικά γνωστές ως setters. Αυτές αλλάζουν την τιμή του πεδίου. Οι setters δεν είναι πολύ συνηθισμένοι στη Cairo. Αν ένα πεδίο μπορεί να τροποποιηθεί ελεύθερα, το πιο συνηθισμένο είναι να το κάνεις απλώς δημόσιο, αλλά είναι χρήσιμοι αν η ενημέρωση του πεδίου πρέπει να έχει παρενέργειες.
Τα structs ορίζονται χρησιμοποιώντας τη λέξη-κλειδί struct, ακολουθούμενη από το όνομα του τύπου που περιγράφει το struct, με κεφαλαίο αρχικό γράμμα:
struct Item {}
Στη συνέχεια, πρόσθετοι τύποι εισάγονται στο σώμα του struct ως πεδία του struct, καθένα με τον δικό του τύπο:
struct Item {
name: String,
weight: f32,
worth: u32,
}
Ένα trait ορίζει ένα σύνολο μεθόδων που μπορούν να υλοποιηθούν από έναν τύπο (εδώ θα επικεντρωθούμε στα structs, αλλά τα traits μπορούν να υλοποιηθούν και σε enums).
Αυτές οι μέθοδοι μπορούν να κληθούν σε στιγμιότυπα του τύπου όταν αυτό το trait υλοποιείται.
Τα traits ορίζονται με τη λέξη-κλειδί trait και μέσα στα traits ορίζουμε τις υπογραφές μεθόδων που θέλουμε να υλοποιήσει ο τύπος μας.
trait ImplTrait {
// Define the method signature
fn new() -> Item;
}
Τέλος, μέθοδοι μπορούν να οριστούν πάνω σε structs μέσα σε ένα μπλοκ impl, το οποίο υλοποιεί το ορισμένο trait:
impl ItemImpl of ImplTrait {
// initializes and returns a new instance of our Item struct
fn new() -> Item {
Item {}
}
}
Δουλεύεις πάνω στην υλοποίηση ενός συστήματος παρακολούθησης υγείας. Ως μέρος αυτού, πρέπει να παρακολουθείς τα στατιστικά υγείας των χρηστών.
Θα ξεκινήσεις με κάποιες κενές συναρτήσεις σε ένα μπλοκ impl, καθώς και με τον ακόλουθο ορισμό struct:
pub struct User {
name: String,
age: u32,
weight: u32,
}
Ο στόχος σου είναι να υλοποιήσεις τις κενές μεθόδους στη struct User που ορίζεται στο μπλοκ impl.
Για παράδειγμα, η μέθοδος new πρέπει να επιστρέφει ένα στιγμιότυπο της struct User με τις καθορισμένες τιμές για name, age και weight.
let mut bob = User::new("Bob", 32, 72);
// Returns: a User with name "Bob", age 32, and weight 72
Η μέθοδος weight πρέπει να επιστρέφει το βάρος του User.
bob.weight();
// Returns: 72
Η μέθοδος set_age πρέπει να ορίζει την ηλικία του User.
bob.set_age(33);
// Updates Bob's age to 33; happy birthday Bob!
Καλή διασκέδαση!
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Cairo με 25 έννοιες68 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.