美文网首页
rust泛型编程范式

rust泛型编程范式

作者: Wu杰语 | 来源:发表于2024-06-26 20:31 被阅读0次

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,都是在类和函数中表现泛型,其原理是想通的,学习的时候要仔细琢磨一下。

相关文章

  • Rust语言编程实例100题-065

    Rust语言编程实例100题-065 题目:泛型练习。泛型并不是Rust特有的概率,在很多强类型的编程语言中也支持...

  • rust函数

    学习rust函数,就需要从范式的角度学习,rust参照的范式有函数式、泛型、面向对象,这里的面向对象并非存粹的面向...

  • Rust入坑指南:海纳百川

    今天来聊Rust中两个重要的概念:泛型和trait。很多编程语言都支持泛型,Rust也不例外,相信大家对泛型也都比...

  • 从Swift函数式编程到设计模式(二)

    Swift是一门多范式编程语言。除了支持面向对象编程范式之外,还支持函数式编程范式,和泛型编程。这使得Swift可...

  • Rust中的泛型

    [TOC] Rust中的泛型 泛型程序设计是程序设计语言的一种风格或范式。泛型允许程序员在强类型程序设计语言中编写...

  • java进阶(一):泛型

    1、泛型简介 所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型,泛型编程是一种编程范式,他利用“参数...

  • [学习笔记]初试rust

    什么是Rust? Rust 是一门系统级编程语言,可以被归纳为通用的、多范式、编译型语言,与C/C++不同的是,R...

  • Rust 简介

    Rust 是什么 Rust 是一门系统级别的通用的、多范式、编译型编程语言,与 C/C++类似。其运行速度理论上也...

  • The Rust programming language 读书

    所有的编程语言都会致力于高效地处理重复概念,Rust 中的泛型(generics)就是这样一种工具。泛型是具体类型...

  • C++11 模板元编程 - 前言

    熟悉C++的程序员都知道,C++是一门多范式编程语言,支持面向过程、面向对象、泛型编程以及函数式编程范式。然而提到...

网友评论

      本文标题:rust泛型编程范式

      本文链接:https://www.haomeiwen.com/subject/bhvjcjtx.html