rust泛型编程范式

1 泛型范式

C++、JAVA泛型范式有非常广泛的应用,也即模版方法和模版类,我们使用非常熟悉。
模版方法和模版类会在编译期间具化,在rust中叫单态化,将模版结构、方法、trait按照具体的类型单态具化为若干拷贝代码。

  • 好处:模版方法和模版类在编译期间,把所有用到的泛型函数的泛型参数展开,生成若干个函数,这样就和普通函数一样,没有任何效率损失。
  • 缺点:编译器需要找到所有用到的不同类型,一个个编译,编译速度会减慢 ,编出来的二进制会比较大,因为泛型函数的二进制代码实际存在 N 份。

Rust的是一种静态强类型语言,其多态有参数多态、特型多态、子类型多态。

  • 参数多态是指,代码操作的类型是一个满足某些约束的参数,而非具体的类型。
  • 特设多态是指同一种行为有多个不同实现的多态。
  • 子类型多态是指,在运行时,子类型可以被当成父类型使用。

2. 参数多态和特型多态

参数多态和特型通过结构体、函数、trait三种语法场景表现出来。

2.1 结构体多态

结构体多态是对相同的数据结构行为的抽象,在rust中也比较常见,例如

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

2.2 函数多态

函数多态也即模版方法, 可以直接进行限定,或者用where语句进行限定(限定 英文是Bound(边界)是一个用于指定泛型类型参数的限制条件

fn print_value<T: std::fmt::Display>(value: T) 
fn print_value<T>(value: T) where T: std::fmt::Display

也可以用+进行多重限定

fn print_value<T: Debug + Display>(value: T) 

另外利用impl,可以进行参数或者返回值约束(impl的好处是解决限定是组合的情况)(注意看下面的注释处,可以返回Itrerator<item=i32>、Box<Itrerator<item=i32>>,甚至更长的组合,这里我们用impl Itrerator<item=i32>就可以解决问题了)

fn combine_vecs<T: (
    v: Vec<i32>,
    u: Vec<i32>,
) -> imp Iterator<Item=i32> {
          // 注意这里可以返回实现了Itrerator<item=i32>的结构,也可以返回满足Box<Itrerator<item=i32>>的结构
}

2.3 trait多态

一个典型的triat模版如下

pub trait Add<Rhs = Self> {
    type Output;

    fn add(self, rhs: Rhs) -> Self::Output;
}

对于trait,有Self、子类型、关联类型几个特性要特别了解

  1. trait多态,第一个要理解的是Self,Self也即结构本身,例如Clone的返回值,Self返回的就是实现了CloneTrait的结构本身,而函数中&self实际是 self: &Self的简写,&mut self是self: &mut Self的简写。
pub trait Clone {
    fn clone(&self) -> Self;
    fn clone_from(&mut self, source: &Self) { ... }
}
  1. trait也有子类型,例如
trait MyTrait : Debug {
}

这里如果结构体实现MyTrait,也必须同时实现Debug的方法,否则编译器会报错。

  1. trait的关联类型,如下:
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

迭代器trait中的Item就是关联类型,实现一个迭代器例子如下:

//(来自标准库中std::env模块的代码)
impl Iterator for Args {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        ...
    }
    ...
}

3. trait object

如下例子,&dyn trait或者Box<dyn trait>,实现了子类型多态。

trait Animal {
    fn speak(&self);
}

struct Dog;

impl Animal for Dog {
    fn speak(&self) {
        println!("Woof!");
    }
}

struct Cat;

impl Animal for Cat {
    fn speak(&self) {
        println!("Meow!");
    }
}

// 等价于 fn name<T: Animal>(animal: T) -> &'static str;
fn name(animal: impl Animal) -> &'static str {
    animal.name()
}

fn main() {
    let animals: Vec<Box<dyn Animal>> = vec![
        Box::new(Dog),
        Box::new(Cat),
    ];

    for animal in animals {
        animal.speak();
    }
}

类似于C++虚表的原理,rust使用了胖指针实现子类型多态, 例子中将具体的Dog和Cat转为胖指针,每个胖指针都有2个字段,为固定大小。一个字段指向数据结构本身,一个字段指向函数表


trait object

3. 小结

rust泛型包括参数泛型和特型泛型(1)数据结构泛型 2)函数泛型 3)trait泛型),也包括子类型泛型(trait object)。对比C++和Java,都是在类和函数中表现泛型,其原理是想通的,学习的时候要仔细琢磨一下。

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

推荐阅读更多精彩内容