やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustの列挙型(enum)

 C/C++/C#などと比べてパワフル。

成果物

参考

定義

fn main() {
    println!("{:?}", IpAddrKind::V4);
    println!("{:?}", IpAddrKind::V6);
}
#[derive(Debug)]
enum IpAddrKind {
    V4,
    V6,
}

匿名タプル構造体型

fn main() {
    println!("{:?}", IpAddr::V4(127, 0, 0, 1)); // error[E0277]: `IpAddr` doesn't implement `std::fmt::Display`
    println!("{:?}", IpAddr::V6(String::from("::1"))); // error[E0277]: `IpAddr` doesn't implement `std::fmt::Display`
}
enum IpAddr {
    V4(u8,u8,u8,u8),
    V6(String),
}

 整数値以外の型をセットできる!

値なし、匿名構造体型、タプル構造体型

fn main() {
    println!("{}", Message::Move{x:0,y:0} == Message::Move{x:0,y:0});
    println!("{}", Message::Move{x:0,y:0} == Message::Move{x:1,y:1});
    println!("{}", Message::Move{x:0,y:0} == Message::Quit);
    use std::mem;
    println!("{}", mem::discriminant(&Message::Move{x:0,y:0}) == mem::discriminant(&Message::Move{x:0,y:0}));
    println!("{}", mem::discriminant(&Message::Move{x:0,y:0}) == mem::discriminant(&Message::Move{x:1,y:1}));
    println!("{}", mem::discriminant(&Message::Move{x:0,y:0}) == mem::discriminant(&Message::Quit));
}
// メッセージをenumで定義する
#[derive(PartialOrd, PartialEq, Debug)]
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

 列挙型値にセットしたい値は匿名構造体として表現する。名前なしなら匿名タプル構造体型。名前付きなら匿名構造体型。

メソッド実装

fn main() {
    let m = Message::Move{x:0,y:0};
    m.call();
    Message::Move{x:1,y:1}.call();
    Message::Quit.call();
    Message::Write(String::from("hello")).call();
    Message::ChangeColor(255,0,0).call();
}
// メッセージをenumで定義する
#[derive(PartialOrd, PartialEq, Debug)]
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
// enumにメソッドを実装する
impl Message {
    fn call(&self) {
        println!("call {:?}", self);
    }
}

 enumにメソッドを実装できる! 構造体とおなじ。

構造体との違い

 列挙型のほうが大きなグルーピングができる。(列挙は構造体定義の配列みたいなイメージ)

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

 上記のメッセージ4種を構造体で定義すると以下。

struct QuitMessage;
struct MoveMessage {
    x: i32,
    y: i32,
}
struct Write(String); // タプル構造体
struct ChangeColor(i32, i32, i32); // タプル構造体

 個別の型になってしまう。

C/C++との比較

言語 概要
C/C++ 整数値とその集合に名前をつけてグルーピングしたもの
Rust 構造体とその集合に名前をつけてグルーピングしたもの。メソッド実装も可

 Rustのenumはクラスの中でも上位(抽象)にあるところで使うイメージ? (そもそもオブジェクト指向言語のクラスと比べるのが間違っていると思うけど)

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで