複数の要素をひとまとまりにし、そのまとまりを1つの単位として扱えると、便利なことがよくあります。Cairoでは、そのようなまとまりを構造体と呼び、まとまりの中の各要素を構造体のフィールドと呼びます。構造体は利用できるフィールドの全体を定義するもので、構造体の具体的な1つの実体はインスタンスと呼ばれます。
さらに、構造体にはメソッドを定義でき、メソッドはフィールドにアクセスできます。その場合、構造体自身はselfと呼ばれます。メソッドがref self: SomeStructを使うと、フィールドを変更、つまり可変にできます。メソッドがself: SomeStructやself: @SomeStructを使う場合、フィールドは変更できません。つまり不変です。可変性を制御することで、借用チェッカーは、Cairoでは並行処理に関するある種のバグがそもそも発生しないようにできます。
この演習では、構造体に2種類のメソッドを実装します。1つは一般にゲッターと呼ばれるものです。ゲッターは、構造体のフィールドを外部に公開しますが、ほかの誰かがその値を変更することはできません。
もう1つの種類のメソッドも実装します。一般にセッターと呼ばれるものです。セッターはフィールドの値を変更します。セッターはCairoではあまり一般的ではありません。フィールドを自由に変更できるなら、単にそれを公開するほうが一般的です。ただし、フィールドの更新に副作用を持たせたい場合には便利です。
構造体はstructキーワードを使って定義し、そのあとに、その構造体が表す型の名前を先頭を大文字にして書きます:
struct Item {}
次に、追加の型を構造体の_フィールド_として構造体の本体に記述します。各フィールドはそれぞれの型を持ちます:
struct Item {
name: String,
weight: f32,
worth: u32,
}
トレイトは、ある型が実装できるメソッドのまとまりを定義します(ここでは構造体に注目しますが、トレイトは列挙型にも実装できます)。これらのメソッドは、そのトレイトを実装している型のインスタンスに対して呼び出せます。トレイトはtraitキーワードで定義し、トレイトの中には、その型に実装してほしいメソッドのシグネチャを書きます。
trait ImplTrait {
// Define the method signature
fn new() -> Item;
}
最後に、メソッドは構造体に対してimplブロックの中で定義でき、このブロックが定義したトレイトを実装します:
impl ItemImpl of ImplTrait {
// initializes and returns a new instance of our Item struct
fn new() -> Item {
Item {}
}
}
健康モニタリングシステムの実装に取り組んでいます。 その一環として、ユーザーの健康統計を記録する必要があります。
まずは、implブロックにあるいくつかのスタブ関数と、次の構造体の定義から始めます。
pub struct User {
name: String,
age: u32,
weight: u32,
}
目標は、implブロックで定義されているUser structのスタブメソッドを実装することです。
たとえば、newメソッドは、指定された名前、年齢、体重を持つUser構造体のインスタンスを返します。
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!
楽しんで取り組んでください!