0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rust enum_dispatch の解説

0
Posted at

Rust enum_dispatch の簡単な解説

Rustで複数の型が同じトレイトを実装している場合、それらを enumでまとめて扱いたいことがあります。

しかし普通のenumでは、enum自体はそのトレイトを実装していないため、そのままメソッドを呼ぶことができません。

そこで便利なのが enum_dispatch です。

これは

enumに対するトレイト実装を自動生成するクレート

です。


インストール

cargo add を使う場合は次のコマンドです。

cargo add enum_dispatch

困るケース(通常のRust)

例えば Animal トレイトがあるとします。

trait Animal {
    fn speak(&self) -> &'static str;
}

2つの実装:

struct Dog;
struct Cat;

impl Animal for Dog {
    fn speak(&self) -> &'static str {
        "woof"
    }
}

impl Animal for Cat {
    fn speak(&self) -> &'static str {
        "meow"
    }
}

これらを enum でまとめます。

enum Pet {
    Dog(Dog),
    Cat(Cat),
}

ここで次のようなコードを書きたくなります。

fn say(pet: Pet) {
    println!("{}", pet.speak());
}

しかしこれは コンパイルできません。

理由は

Dog → Animal
Cat → Animal
Pet → Animal ではない

からです。

そのため普通は次のようなコードを書きます。

impl Animal for Pet {
    fn speak(&self) -> &'static str {
        match self {
            Pet::Dog(d) => d.speak(),
            Pet::Cat(c) => c.speak(),
        }
    }
}

この match はよく出てくる 定型コードです。


enum_dispatch を使う

enum_dispatch を使うと、この match自動生成してくれます。

use enum_dispatch::enum_dispatch;

#[enum_dispatch]
trait Animal {
    fn speak(&self) -> &'static str;
}

実装は普通に書きます。

struct Dog;
struct Cat;

impl Animal for Dog {
    fn speak(&self) -> &'static str {
        "woof"
    }
}

impl Animal for Cat {
    fn speak(&self) -> &'static str {
        "meow"
    }
}

そして enum に attribute を付けます。

#[enum_dispatch(Animal)]
enum Pet {
    Dog(Dog),
    Cat(Cat),
}

すると次のような実装が 自動生成されます(イメージ)

impl Animal for Pet {
    fn speak(&self) -> &'static str {
        match self {
            Pet::Dog(d) => d.speak(),
            Pet::Cat(c) => c.speak(),
        }
    }
}

使い方

これで次のコードが書けるようになります。

fn say(pet: Pet) {
    println!("{}", pet.speak());
}

つまり

Dog → Animal
Cat → Animal
Pet → Animal (自動生成)

という関係になります。


まとめ

enum_dispatch

  • enum に対する trait実装を自動生成する
  • 手書き match をなくせる
  • dyn Trait を使わずにポリモーフィズムを書ける

という便利なクレートです。

「複数の実装をenumでまとめて扱う設計」ではとても相性の良いライブラリです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?