Rustのenumには三つの使い方がある。
まずはC言語におけるunionに近い使い方。
以下ではC_Union_Like型を定義しているが、この変数はi32,f32,Stringの「いずれか一つ」を代入することができる。
// Rust の enum は、C言語のunionに近い使い方ができる。 // 以下ではivalue,fvalue,svalueの三つのバリアントを定義しているが、 // 一度に有効なのは一つだけ。 enum C_Union_Like{ ivalue(i32), fvalue(f32), svalue(String), }
fn main() { // C_Union_Likeのivalueにi32を入れる。 let mut cu:C_Union_Like = C_Union_Like::ivalue(33); // fvalueに入れたので、cuはf32を持つようになった cu = C_Union_Like::fvalue(7.5); // svalueに入れたので、cuはStringを持つようになった cu = C_Union_Like::svalue("hello".to_string()); // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。 // cu がどの値を持っているかを知る方法は // パターンマッチングでマッチするかで判断する // cu が ivalue にマッチするなら、iiを定義し、ivalueの値を代入 if let C_Union_Like::ivalue(ii)=cu { println!("int is used. {}",ii); } else if let C_Union_Like::fvalue(ff)=cu{ println!("float is used. {}",ff); } else if let C_Union_Like::svalue(ss)=cu{ println!("String is used. {}",ss); } }
このプログラムは、C/C++における以下に近い。
struct C_Union_Like { int type; union { int ivalue; float fvalue; //std::string svalue; // これはC++ではできないが、Rustならできる }; }; int main() { C_Union_Like cu; cu.type = 0; cu.ivalue = 33; cu.type = 1; cu.fvalue = 7.5f; switch (cu.type) { case 0: printf("int is used. %d \n", cu.ivalue); break; case 1: printf("float is used. %d \n", cu.fvalue); break; } }
Rustのenumは、C/C++のunionと違ってStringなどの複雑な型を取ることができる。さらに型情報も自動で持つので、unionのように自分で管理する必要がない。注意点として、今何が入っているかはパターンマッチングで判断する。上ではif letを使っているが、matchを使ってもよい。
fn main() { // C_Union_Likeのivalueにi32を入れる。 let mut cu:C_Union_Like = C_Union_Like::ivalue(33); // svalueに入れたので、cuはStringを持つようになった cu = C_Union_Like::svalue("hello".to_string()); // fvalueに入れたので、cuはf32を持つようになった cu = C_Union_Like::fvalue(7.5); // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。 // cu がどの値を持っているかを知る方法は // パターンマッチングでマッチするかで判断する // cuの取りうるバリアントが多い場合はmatchのほうが読みやすい match cu{ C_Union_Like::ivalue(ii) => { println!("int is used. {}",ii); }, C_Union_Like::fvalue(ff) => { println!("float is used. {}",ff); }, C_Union_Like::svalue(ss) => { println!("String is used. {}",ss); }, _ =>{} } }