Es ist oft nützlich, eine Sammlung von Elementen zu einer Gruppe zusammenzufassen und diese Gruppen als Einheiten zu behandeln. In Cairo nennen wir eine solche Gruppe ein Struct, und jedes Element ist eines der Felder des Structs. Ein Struct legt die allgemeine Menge der verfügbaren Felder fest, aber ein bestimmtes Exemplar eines Structs wird als Instanz bezeichnet.
Außerdem können für Structs Methoden definiert werden, die Zugriff auf die Felder haben.
Das Struct selbst wird in diesem Fall als self bezeichnet.
Wenn eine Methode ref self: SomeStruct verwendet, können die Felder geändert, also mutiert werden.
Wenn eine Methode self: SomeStruct oder self: @SomeStruct verwendet, können die Felder nicht geändert werden: Sie sind unveränderlich.
Die Kontrolle über die Veränderbarkeit hilft dem Borrow-Checker dabei, sicherzustellen, dass ganze Klassen von Nebenläufigkeitsfehlern in Cairo gar nicht erst auftreten.
In dieser Übung implementierst du zwei Arten von Methoden für ein Struct. Die erste Art wird allgemein als Getter bezeichnet: Sie machen die Felder des Structs nach außen sichtbar, ohne dass jemand anderes diesen Wert verändern kann.
Außerdem implementierst du Methoden einer anderen Art, die allgemein als Setter bekannt sind. Diese ändern den Wert des Feldes. Setter sind in Cairo nicht sehr verbreitet. Wenn ein Feld frei geändert werden darf, ist es üblicher, es einfach öffentlich zu machen. Nützlich sind sie aber, wenn das Aktualisieren des Feldes Nebenwirkungen haben soll.
Structs werden mit dem Schlüsselwort struct definiert, gefolgt vom großgeschriebenen Namen des Typs, den das Struct beschreibt:
struct Item {}
Weitere Typen werden dann als Felder in das Struct aufgenommen, jedes mit seinem eigenen Typ:
struct Item {
name: String,
weight: f32,
worth: u32,
}
Ein Trait definiert eine Menge von Methoden, die von einem Typ implementiert werden können (wir konzentrieren uns hier auf Structs, aber Traits können auch für Enums implementiert werden).
Diese Methoden können für Instanzen des Typs aufgerufen werden, sobald dieses Trait implementiert ist.
Traits werden mit dem Schlüsselwort trait definiert, und innerhalb eines Traits definieren wir die Methodensignaturen, die unser Typ implementieren soll.
trait ImplTrait {
// Define the method signature
fn new() -> Item;
}
Schließlich können Methoden für Structs innerhalb eines impl-Blocks definiert werden, der das definierte Trait implementiert:
impl ItemImpl of ImplTrait {
// initializes and returns a new instance of our Item struct
fn new() -> Item {
Item {}
}
}
Du arbeitest daran, ein System zur Gesundheitsüberwachung zu implementieren. Dabei musst du die Gesundheitsstatistiken der Nutzer verfolgen.
Du startest mit einigen Stub-Funktionen in einem impl-Block sowie der folgenden struct-Definition:
pub struct User {
name: String,
age: u32,
weight: u32,
}
Dein Ziel ist es, die Stub-Methoden des User-Structs zu implementieren, das im impl-Block definiert ist.
Zum Beispiel sollte die new-Methode eine Instanz des User-Structs mit den angegebenen Werten für Name, Alter und Gewicht zurückgeben.
let mut bob = User::new("Bob", 32, 72);
// Returns: a User with name "Bob", age 32, and weight 72
Die weight-Methode sollte das Gewicht des User zurückgeben.
bob.weight();
// Returns: 72
Die set_age-Methode sollte das Alter des User setzen.
bob.set_age(33);
// Updates Bob's age to 33; happy birthday Bob!
Viel Spaß!
Melde dich bei Exercism an, um Cairo mit 25 Konzepte68 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.