rust学习七、枚举

打印 上一主题 下一主题

主题 866|帖子 866|积分 2598

枚举是十分特别的范例,是由于和大部门语言中看起来不太一样。
最大的不同之一在于:允许每个成员具有不同的范例的属性
 
注:本文内容根据有关章节编写
如果没有特别说明,"rust学习"系列基本上都是根据此书编写,不再在后续的篇幅中说明
一、定义、赋值和打印

结论:
1.rust枚举范例相当之怪异 2.枚举的定义中,允许成员包含数据,也可以不包含数据。3.当枚举范例中包含数据时,不同的枚举实例还可以包含不同的范例的数据。4.枚举的成员只能包含(a-z, A-Z)、数字(0-9)、下划线(_)以及 Unicode 非字母数字字符    不能以数字开头   当每个枚举成员都可以不同的时候,我们把它明白成java的Object范例即可。  总之,rust的枚举范例极其怪,不同于于别的语言     枚举的定义中,枚举成员的命名方式为:首字母大写(仅仅是发起)5.枚举可以有方法,和struct布局类似,定义的方式也类似,放在枚举外,而不是在内部 示例
  1. #[derive(Debug)]
  2. enum simple_enum {
  3.     Man,
  4.     Women,
  5.     Other
  6. }
  7. //b. 枚举类型中包含数据
  8. #[derive(Debug)]
  9. enum color {
  10.     Red,
  11.     Green = 3
  12. }
  13. //c.枚举类型中包含多个数据,且都是一样的
  14. #[derive(Debug)]
  15. #[derive(PartialEq)]
  16. enum grade {
  17.     A(u32,String),
  18.     B(u32,String),
  19.     C(u32,String)
  20. }
  21. //枚举的方法,定义上了struct方法类似,都是impl,&self
  22. impl grade {
  23.     fn print(&self) {   
  24.         //这个tmd也太麻烦了吧
  25.         match self {
  26.             grade::A(a,b) => println!("{}-{}",a,b),
  27.             grade::B(a,b) => println!("{}-{}",a,b),
  28.             grade::C(a,b) => println!("{}-{}",a,b)
  29.         }
  30.     }
  31. }
  32. #[derive(Debug)]
  33. enum food<'a>{
  34.     蔬菜([String;5]),
  35.     禽肉,
  36.     猪肉,
  37.     牛羊肉,
  38.     海鲜,
  39.     大米,
  40.     水果(&'a str,&'a str,&'a str)
  41. }
  42. fn main() {
  43.     let a = simple_enum::Man;
  44.     println!("{:?}",a);
  45.     // 使用println! :?宏打印枚举的时候,变量名称不能同枚举成员。否则会报错
  46.     let gr = color::Green;  
  47.     println!("{:?}",gr);
  48.     let r = color::Red;
  49.     println!("{:?}",r);
  50.     let grade_a = grade::A(10,String::from("差"));
  51.     let grade_a1=grade::A(9,String::from("差011"));
  52.     grade_a.print();
  53.     println!("{:?}",grade_a);
  54.     if (grade_a == grade_a1){
  55.         println!("相等");
  56.     }
  57.     else{
  58.         println!("不相等");
  59.     }
  60.     let fruit= food::水果("苹果","香蕉","梨子");
  61.     println!("{:?}",fruit);
  62.     print_first_fruit_member(fruit);
  63.     let v = food::蔬菜(["白菜".to_string(),"萝卜".to_string(),"黄瓜".to_string(),"冬瓜".to_string(),"南瓜".to_string()]);
  64.     println!("{:?}",v);
  65. }
  66. fn print_first_fruit_member<'a>(fruit: food<'a>) {
  67.     if let food::水果(first, second, third) = fruit {
  68.         println!("{},{},{}", first,second,third);
  69.     } else {
  70.         println!("The provided food is not a fruit.");
  71.     }
  72. }
复制代码
上例中,food允许不同成员有不同的范例值。
 
二、特别的枚举-Option

按照作者的意思,Option是一个很有用的枚
Option{
 Some(T),
 None
}

特别点在于:
1.定义于标准库中
2.它乃至被包含在了 prelude 之中,你不必要将其显式引入作用域
3.它的成员也是云云,可以不必要 Option:: 前缀来直接利用 Some 和 None


有用是怎么表现出来的?

1.首先Option具有很多方法,比如is_some()、is_none()、unwrap()等
2.Option可以作为函数参数,比如fn some_function(option: Option)


以下是重点(基本上摘抄的):
那么当有一个 Option 的值时,怎样从 Some 成员中取出 T 的值来利用它呢?
Option 枚举拥有大量用于各种情况的方法:
你可以查看它的文档。熟悉 Option 的方法将对你的 Rust 之旅非常有用(原文) 示例
  1. fn main() {
  2.     let some_number = Some(5); // some_number的类型是Option<i32>
  3.     let some_string = Some("a string"); // some_string的类型是Option<&str>
  4.     let absent_number: Option<i32> = None; // absent_number的类型是Option<i32>
  5.     println!("some_number is {:?}", some_number);
  6.     println!("some_string is {:?}", some_string);
  7.     println!("absent_number is {:?}", absent_number);
  8.     println!("absent_number is {:?}", absent_number.is_none());
  9.     let name:String;
  10.     name.push_str("abc");
  11. }
复制代码
非常有用? 还没有体会出来,先记着! 
三、match和枚举

这里主要讨论怎样匹配枚举的值,rust的办理方案是match。
1.match某种程度上可以看作rust中if-else的升级版,只不过match偶然候可以让我们少打印一些代码而已
match不像java的switch那么傻瓜(传统),必要在每个分支上break,否则会继续执行下一个分支,固然有那种情况存在,但是绝大部门时候,
我们并不必要break。
rust的match和新版本的java switch写法更加一致,已经不必要break了,且不会傻乎乎地每个匹配已往

2.趁便说一下,rust的创始人很喜好下划线。所以下划分可以分割变量,也可以单独作为一个变量,但是不发起这么做
3.关于分支值的匹配
    a.rust的分支匹配是穷尽的,意思就是编译器如果发现你存在一些未匹配的分支,就会报错。  我们记着这个就可以了,由于编译器很贴心第处理了这个。
       这一点,的确比很多编译器好多了。
    b.rust可以利用多种方式匹配某个分支值,包括单个值、多个值、所有值
    c.rust利用下划线_来表示所有值,这样我们就可以直接利用这个变量了。这个倒是比很多语言的default稍微省事一些。这个并不是重点
    d._和other都可以表示所有值,能一起用,不会编译错误,但是固定有一个分支不可达到
     这意味着,rust的编译器目前固然很贴心,但也不会浪费过多的时间去判断是否具有相同的分支--由于它允许有相同的分支,但是
     它的匹配机制使得只会有其中一个分支被执行,别的相同的并会被处理
    e.当某个分支值满足之后,匹配代码就结束了,不会像传统的java switch那么傻叉继续执行背面的。这个符合大部门人的思维
 
示例
  1. /**
  2. * 年代枚举
  3. */
  4. #[derive(Debug)]
  5. enum Age{Year1970,OtherYear}
  6. /**
  7. * 硬币枚举
  8. */
  9. enum Coin{一分(Age),二分,五分,一角,贰角,五角,一元}
  10. /**
  11. * 文明枚举
  12. */
  13. #[derive(Debug)]
  14. enum Civil{中国(Age),欧洲,美国,非洲}
  15. fn main(){
  16.     let coin = Coin::五分;
  17.     let one =Coin::一元;
  18.     match_branch_with_multiple_method(coin);
  19.     match_branch_with_multiple_method(one);
  20.     let civil = Civil::中国(Age::Year1970);
  21.     let _ = Civil::欧洲;   //奇特的无意义的变量名称_,可以用,但是不建议。因为你无法直接传递,转赋也不方便,也不利于维护
  22.     //let bad_=_;  //这样会报错
  23.     //match_and_use_branch_value(_) //这样会报错
  24.     let _欧洲 = Civil::欧洲;
  25.     match_and_use_branch_value(civil);
  26.     match_and_use_branch_value(_欧洲);
  27.    
  28. }
  29. fn match_branch_with_multiple_method(coin:Coin){
  30.     //演示如何匹配多值分支的方式:单个值、多个值、所有值
  31.     match coin{
  32.         Coin::一分(Age::Year1970) => println!("一分"),  //匹配分支特定值
  33.         Coin::一分(_) => println!("一分"),   //匹配分支所有值
  34.         Coin::一分(Age::OtherYear) |   Coin::一分(Age::Year1970)  => println!("一分"), //匹配分支多个值
  35.         Coin::二分 => println!("二分"),
  36.         Coin::五分 => println!("五分"),
  37.         Coin::一角 => println!("一角"),
  38.         Coin::五角 => println!("五角"),
  39.         other => println!("一元 of other"),
  40.         _=> println!("一元")
  41.     };
  42. }
  43. fn  match_and_use_branch_value(civil:Civil){
  44.     //这种方式,可以利用类似匹配元组元素的方式,直接捕获分支值,并使用
  45.     match civil {
  46.         Civil::中国(age) => println!("有小聪明的中国:{:?},偶尔有一些亮色能拯救他们",age),  //自动从civil中捕获age值
  47.         Civil::欧洲 => println!("肮胀但又聪明的欧洲"),
  48.         _ => println!("{:?}",civil)   //如果把这个匹配去掉,那么会引发编译错误: patterns `Civil::美国` and `Civil::非洲` not covered
  49.     };
  50. }
复制代码
 
如上例,match对枚举的匹配是穷尽的,这意味着一个值没有匹配,编译器就报错,这对于工程师倒是挺友好的!
 
四、语法糖if let

示例
  1. #[derive(Debug)]
  2. enum Age{Year1970,OtherYear}
  3. /**
  4. * 硬币枚举
  5. */
  6. enum Coin{一分(Age),二分,五分,一角,贰角,五角,一元}
  7. fn main(){
  8.     let coin = Coin::一分(Age::Year1970);
  9.     match coin{
  10.         Coin::一分(Age::Year1970) => println!("70特有硬币?"),
  11.         _=>println!("不是一分硬币")
  12.     }
  13.     //rust 的语法糖
  14.     if let Coin::一分(Age::Year1970) = coin{
  15.         println!("70特有硬币?");
  16.     }else{  
  17.         println!("不是一分硬币");
  18.     }
  19.    
  20.     //不带 else的if let
  21.     if let Coin::一分(Age::OtherYear)=coin{
  22.         println!("不是70特有硬币");
  23.     }
  24. }
复制代码
 
语法糖这个东西没有什么可说的,就是图方便而已。
如果没有ide和代码助手,那么的确还是不错的! 但你如果有ide和代码助手,那么这些语法糖的主要作用就是困扰。
五、小结

总而言之,rust的枚举和大部门语言看起来并没有什么本质的上的区别,但的确又有一些区别。
rust发明人的宗旨:让语言尽量用起来方便一些。 看起来似乎得到了表现。   就我个人而言,不是太苟同!
rust的编译器的大作用,在这里有了表现!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

不到断气不罢休

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表