Rustの構造体(Struct)入門|データ構造の作成と活用

先生

Rustの構造体はデータの設計図!型、フィールド、メソッドをマスターして、君だけのオリジナルデータ構造を創り出そう🚀

Rustの構造体(Struct)とは?基本を理解しよう

Rustにおける構造体(Struct)は、複数の異なる型のデータをひとまとめにして扱うためのデータ構造です。オブジェクト指向プログラミングにおけるクラスのような役割を果たしますが、Rustの構造体はメソッドを持つだけでなく、データの保持にも特化しています。

構造体を使うことで、関連するデータをグループ化し、コードの可読性と保守性を向上させることができます。例えば、Personという構造体を作成し、名前(name)、年齢(age)、住所(address)といった情報をまとめて管理できます。

Rustの構造体には、主に以下の3種類があります。

名前付きフィールド構造体 (Named-Field Structs): フィールドに名前が付いている最も一般的な構造体です。

タプル構造体 (Tuple Structs): フィールドに名前がなく、型のみが定義された構造体です。

ユニット構造体 (Unit Structs): フィールドを持たない構造体で、主にジェネリクスやトレイト境界で使用されます。

この記事では、これらの構造体の使い方を詳しく解説していきます。

名前付きフィールド構造体の作成と利用

名前付きフィールド構造体は、最も一般的な構造体であり、フィールドに名前を付けてデータを格納します。これにより、各フィールドの意味が明確になり、コードの可読性が向上します。

struct Person {
    name: String,
    age: u32,
    address: String,
}

上記の例では、Person構造体を定義しています。nameは文字列型(String)、ageは32ビット符号なし整数型(u32)、addressも文字列型(String)です。

構造体のインスタンスを作成するには、次のようにします。

fn main() {
    let person = Person {
        name: String::from("Alice"),
        age: 30,
        address: String::from("Tokyo"),
    };

    println!("Name: {}", person.name);
    println!("Age: {}", person.age);
    println!("Address: {}", person.address);
}

上記のコードでは、Person構造体のインスタンスを作成し、各フィールドに値を代入しています。そして、println!マクロを使って、各フィールドの値を出力しています。

構造体のフィールドには、ドット演算子(.)を使ってアクセスできます。

タプル構造体:簡潔なデータ表現

タプル構造体は、フィールドに名前がない構造体です。名前付きフィールド構造体よりも簡潔にデータを表現できますが、フィールドの意味が名前で示されないため、可読性が低下する可能性があります。

struct Color(u8, u8, u8);

上記の例では、Color構造体を定義しています。これは、赤(u8)、緑(u8)、青(u8)の値を格納するための構造体です。

タプル構造体のインスタンスを作成するには、次のようにします。

fn main() {
    let red = Color(255, 0, 0);

    println!("Red: {}", red.0);
    println!("Green: {}", red.1);
    println!("Blue: {}", red.2);
}

上記のコードでは、Color構造体のインスタンスを作成し、各フィールドに値を代入しています。そして、println!マクロを使って、各フィールドの値を出力しています。

タプル構造体のフィールドには、ドット演算子(.)とフィールドのインデックスを使ってアクセスできます。インデックスは0から始まります。

ユニット構造体:状態を持たない型の定義

ユニット構造体は、フィールドを持たない構造体です。状態を持たない型を定義する際に使用されます。ジェネリクスやトレイト境界と組み合わせて使用されることが多いです。

struct Unit;

上記の例では、Unit構造体を定義しています。これは、フィールドを持たない空の構造体です。

ユニット構造体のインスタンスを作成するには、次のようにします。

fn main() {
    let unit = Unit;

    println!("Unit struct");
}

上記のコードでは、Unit構造体のインスタンスを作成しています。ユニット構造体はフィールドを持たないため、インスタンスを作成する際に値を指定する必要はありません。

ユニット構造体は、主にマーカーとして使用されます。

構造体とメソッド

構造体には、メソッドを関連付けることができます。メソッドは、構造体のインスタンスに対して実行される関数です。メソッドを使うことで、構造体の振る舞いを定義できます。

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

上記の例では、Rectangle構造体と、その構造体に関連付けられたareaメソッドを定義しています。areaメソッドは、Rectangleの面積を計算して返します。

メソッドを呼び出すには、次のようにします。

fn main() {
    let rect = Rectangle {
        width: 10,
        height: 5,
    };

    println!("Area: {}", rect.area());
}

上記のコードでは、Rectangle構造体のインスタンスを作成し、areaメソッドを呼び出して、面積を出力しています。

implキーワードは、構造体に関連付けられたメソッドを定義するために使用されます。&selfは、メソッドが構造体のインスタンスへの参照を受け取ることを示します。

参考リンク

まとめ

この記事では、Rustの構造体について解説しました。構造体は、関連するデータをひとまとめにして扱うための強力なツールです。名前付きフィールド構造体、タプル構造体、ユニット構造体の3種類があり、それぞれ異なる用途で使用されます。構造体とメソッドを組み合わせることで、より複雑なデータ構造と振る舞いを定義できます。Rustの構造体を理解し、効果的に活用することで、より効率的で保守性の高いコードを書くことができるでしょう。