はじめに
これはあくまでメモなので、基本的にググってわかるようなことは詳しく書きません。
よろしくお願いします。
また、以下のプログラムでは面倒なのでfn main() {}
を省略することがあります。
ご承知おきください。
おさらい
前回は2版の4章の4.3に目を通して、以下のことを学びました。
- スライスの扱い方
以下のリンクで参照できます。
https://qiita.com/task4233/items/5f9e5868ba5cfbc56739
5. 構造体
structまたは、構造体は、意味のあるグループを形成する複数の関連した値をまとめ、名前付けできる独自のデータ型です。
だそうです。
構造体の定義
構造体は以下のlist1
のように定義します。
慣習として構造体の1文字目は大文字とされています。
末尾に;
は必要ありません。
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
インスタンス化
構造体は以下のlist2
のようにインスタンスを生成できます。
こちらはuser1
という変数に対する束縛なので、末尾に;
が必要です。
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
生成されたインスタンスの要素にアクセスにはドット記法を使います。
ドット記法を使用することで、以下のlist3
のように値を変更したり参照したりすることができます。
ただし、値を変更する場合はミュータブルにしておく必要があります。
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
println!("{}", user1.email);
user1.email = String::from("anotheremail@example.com"); // 値の変更
println!("{}", user1.email);
// [output]
// someone@example.com
// anotheremail@example.com
}
また、インスタンス化する際にその都度全ての要素を設定するのが面倒な時は、以下のlist4
のような関数を作成することで簡潔にインスタンス化できるようになります。
ここで、フィールドと変数名が同名の時は変数名のみで書くこともできます。
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn build_user(email: String, username: String) -> User {
User {
// フィールドと変数名が同じなので、
// email,
// のみでも可
email: email,
// 同様に
// username,
// のみでも可
username: username,
active: true,
sign_in_count: 1,
}
}
fn main() {
// 以下の宣言と同義
let mut user1 = build_user(String::from("someone@example.com"), String::from("someusername123"));
// let mut user1 = User {
// email: String::from("someone@example.com"),
// username: String::from("someusername123"),
// active: true,
// sign_in_count: 1,
// };
}
他のインスタンスから新たにインスタンスを生成する
以下のlist5
のように、他のインスタンスと異なる部分のみを記述することで新たなインスタンスを生成できる。
ここで、..
というきほうにより、セットしていないフィールドを明示的に与えられたインスタンスのフィールドと同じ値になるように指定します。
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn main() {
let mut user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
let user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername567"),
..user1
};
}
タプル構造体
タプル構造体は、以下のlist6
のように定義できます。
ここで、Color
とPoint
は3つのi32
からできていますが、別の型として認識されることに注意しましょう。
しかし、要素でみればi32
なので要素のみを使用すれば問題はありません。
// Color(R, G, B)
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
let Point(a, b, c) = origin;
let Blue = Color(a, b, 255); // Point型の要素のみ(i32)をとっているのでエラーは起きない
let Color(r, g, b) = Blue;
println!("(r, g, b) = ({}, {}, {})", r, g, b);
// [output]
// (r, g, b) = (0, 0, 255)
おわりに
2版5章5.1では以下のことが書かれていました。
- 構造体の基礎的な扱い方
記法は違えど、構造体の概念はやはりどの言語でもあまり変わりませんね。
次回は構造体を使用したプログラム例を扱おうと思います。