Moveの型システムは、カスタムタイプを定義する際にその真価を発揮します。ユーザー定義型は、アプリケーションの具体的なニーズに合わせてカスタム調整することができます。これはデータレベルだけでなく、その振る舞いにおいてもです。このセクションでは、構造体の定義とその使用方法を紹介します。
カスタムタイプを定義するには、struct
キーワードの後にタイプの名前を続けて使用します。名前の後には、構造体のフィールドを定義できます。各フィールドは field_name: field_type
の構文で定義されます。フィールド定義はコンマで区切られなければなりません。フィールドは他の構造体を含む任意のタイプが可能です。
Moveは再帰的な構造体をサポートしていないため、構造体が自身をフィールドとして含むことはできません。
/// アーティストを表す構造体
public struct Artist {
/// アーティストの名前
name: String,
}
/// 音楽レコードを表す構造体
public struct Record {
/// レコードのタイトル
title: String,
/// レコードのアーティスト。`Artist`タイプを使用
artist: Artist,
/// レコードがリリースされた年
year: u16,
/// レコードがデビューアルバムかどうか
is_debut: bool,
/// レコードのエディション
edition: Option<u16>,
}
上記の例では、5つのフィールドを持つRecord
構造体を定義しています。title
フィールドはString
型、artist
フィールドはArtist
型、year
フィールドはu16
型、is_debut
フィールドはbool
型、edition
フィールドはOption<u16>
型です。edition
フィールドはエディションがオプショナルであることを表すためにOption<u16>
型を使用しています。
構造体はデフォルトでプライベートであり、定義されたモジュールの外部からはインポートおよび使用することができません。フィールドもプライベートであり、モジュールの外部からアクセスすることはできません。異なる可視性修飾子についての詳細は可視性で説明しています。
構造体のフィールドはプライベートであり、構造体を定義するモジュール内でのみアクセスが可能です。他のモジュールで構造体のフィールドを読み書きするには、構造体を定義するモジュールがフィールドにアクセスするための公開関数を提供している必要があります。
構造体の定義方法について説明しました。次に、構造体を初期化して使用する方法を見てみましょう。構造体は struct_name { field1: value1, field2: value2, ... }
の構文を使用して初期化できます。フィールドは任意の順序で初期化でき、すべてのフィールドを設定する必要があります。
let mut artist = Artist {
name: b"The Beatles".to_string()
};
上記の例では、Artist
構造体のインスタンスを作成し、name
フィールドに文字列 "The Beatles" を設定しています。
構造体のフィールドにアクセスするには、フィールド名の前に.
演算子を使用します。
// `Artist`構造体の`name`フィールドにアクセス
let artist_name = artist.name;
// `Artist`構造体のフィールドにアクセス
assert!(artist.name == string::utf8(b"The Beatles"), 0);
// `Artist`構造体の`name`フィールドを変更
artist.name = string::utf8(b"Led Zeppelin");
// `name`フィールドが変更されたことを確認
assert!(artist.name == string::utf8(b"Led Zeppelin"), 1);
構造体を定義するモジュールのみがそのフィールドにアクセスできます(可変および不変の両方)。したがって、上記のコードはArtist
構造体と同じモジュール内にある必要があります。
構造体はデフォルトで非破棄可能であり、初期化された構造体の値は使用されなければなりません:ストアされるかアンパックされます。構造体のアンパックは、それをフィールドに分解することを意味します。これはlet
キーワードに続いて構造体名とフィールド名を使用して行われます。
// `Artist`構造体をアンパックし、`name`フィールドの値を持つ新しい変数`name`を作成
let Artist { name } = artist;
上記の例では、Artist
構造体をアンパックし、name
フィールドの値を持つ新しい変数name
を作成しています。変数が使用されていないため、コンパイラは警告を発生させます。警告を抑制するには、変数が意図的に使用されていないことを示すためにアンダースコア_
を使用できます。
// `Artist`構造体をアンパックし、`name`フィールドを無視
let Artist { name: _ } = artist;