rust 泛型

1、rust标准库#Option

1. Option在rust标准库中的定义

enum Option<T> {
    Some(T),
    None,
}

2. Option的典型用法

fn main()
{
  let x: Option<i32> = None;
  let y: Option<i32> = Some(5);
  let z: Option<f64> = Some(5.0f64);

  println!("{:?}", x);
  println!("{:?}", y);
  println!("{:?}", z);
}
➜  main make
rustc main.rs
./main
None
Some(5)
Some(5.0)
➜  main

3. match 解包 Option

fn main()
{
  let x: Option<i32> = None;
  let y: Option<i32> = Some(5);
  let z: Option<f64> = Some(5.0f64);

  match x {
    Some(x) => { println!("x = {}", x) },
    None => { println!("x = None") },
  }

  match y {
    Some(y) => { println!("y = {}", y) },
    None => { println!("y = None") },
  }

  match z {
    Some(z) => { println!("z = {:?}", z) },
    None => { println!("z = None") },
  }
}
➜  main make
rustc main.rs
./main
x = None
y = 5
z = 5.0
➜  main

4. if let 解包 Option

fn main()
{
  let x: Option<i32> = None;
  let y: Option<i32> = Some(5);
  let z: Option<f64> = Some(5.0f64);

  if let Some(val) = x {
    println!("val = {}", val);
  } else {
    println!("x = None");
  }

  if let Some(val) = y {
    println!("val = {}", val);
  } else {
    println!("y = None");
  }

  if let Some(val) = z {
    println!("val = {:?}", val);
  } else {
    println!("z = None");
  }
}
➜  main make
rustc main.rs
./main
x = None
val = 5
val = 5.0
➜  main

5. while let 解包 Option

fn main()
{
  // 可变绑定的可选值
  let mut num: Option<i32> = Some(0);
  
  // while let 解包/打包 Option类型的变量
  while let Some(i) = num {
    if i > 5 {
      num = None; // 可选值赋值为None
      break;
    } else {
      print!("{}, ", i); 
      num = Some(i+1); // 可选值+1后,继续打包为可选值
    }
  }
  println!(""); 
  println!("num = {:?}", num);
}
➜  main make
rustc main.rs
./main
0, 1, 2, 3, 4, 5,
num = None
➜  main

2、类似于C++模板编程

1. 函数模板

fn make_pair<T, U>(a: T, b: U) -> (T, U) {
  (a, b)
}

fn main()
{
  let couple1 = make_pair("man", "female");
  println!("couple1 = {:?}", couple1);

  let couple2 = make_pair(99i32, 109f64);
  println!("couple2 = {:?}", couple2);
}
➜  main make
rustc main.rs
./main
couple1 = ("man", "female")
couple2 = (99, 109.0)
➜  main

2. 函数模板 + 面向接口

// 接口1
trait Man {
  fn name(&self) -> String;
}

// 接口2
trait Animal {
  fn name(&self) -> String;
}

// 接口3
trait Runnable {
  fn run(&self);
}

fn make_pair<T, U>(a: T, b: U) -> (T, U) 
  where T: Man, 
        U: Animal + Runnable // 模板参数U必须实现两个接口
{
  (a, b)
}

fn main()
{}

3. 类(struct)模板

#[derive(Debug)]
struct Point<T> {
  x: T,
  y: T,
}

fn main()
{
  let int_origin = Point { x: 0, y: 0 };
  let float_origin = Point { x: 0.0, y: 0.0 };

  println!("{:?}", int_origin);
  println!("{:?}", float_origin);
}
➜  main make
rustc main.rs
./main
Point { x: 0, y: 0 }
Point { x: 0.0, y: 0.0 }
➜  main

3、type 关联模板参数类型

1. 接口具体实现

// 接口
trait Graph {
  type N; // 模板参数1
  type E; // 模板参数2

  fn has_edge(&self, &Self::N, &Self::N) -> bool; // 返回bool
  fn edges(&self, &Self::N) -> &Vec<Self::E>; // 返回Vec数组的引用(临时使用权)
}

// 实体类
struct Node;
struct Edge;
struct SimpleGraph {
  edges: Vec<Edge>
}

// 给实体类增加接口实现
impl Graph for SimpleGraph {
  // 1. 给接口中模板参数,确定具体的数据类型
  type N = Node;
  type E = Edge;

  // 2. 接口方法实现1
  fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
    return true;
  }

  // 3. 接口方法实现2
  fn edges(&self, n: &Node) -> &Vec<Edge> { //注意:-> Vec<E> 中的模板参数E要替换为具体数据类型
    return &(self.edges);
  }
}

fn main()
{
  let graph = SimpleGraph {edges: vec![Edge{}, Edge{}, Edge{}]};
  let object = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
}
➜  main make
rustc main.rs
./main
➜  main

2. < T > 绑定模板参数的接口作为函数参数类型

// 接口定义
trait Graph<N, E> {
  // 接口中方法定义时,函数形参不需要使用参数名
  fn has_edge(&self, &N, &N) -> bool;
  fn edges(&self, &N) -> Vec<E>;
}

// 全局函数,函数形参的类型为接口类型
// => 必须先传入【N、E】的数据类型
// => 再确定【Graph<N, E>】的数据类型
fn distance<N, E, G: Graph<N, E>>(
  graph: &G, 
  start: &N, 
  end: &N) -> u32 {
  return 99;
}

fn main()
{}

3. type绑定模板参数的接口作为函数参数类型

// 接口定义
trait Graph {
  type N;
  type E;

  fn has_edge(&self, &Self::N, &Self::N) -> bool;
  fn edges(&self, &Self::N) -> Vec<Self::E>;
}

// 全局函数,函数形参的类型为接口类型
fn distance<G: Graph>(
  graph: &G, 
  start: &G::N, 
  end: &G::N) -> i32 {
  return 99;
}

fn main()
{}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容