Rust 类型、泛型和特征

2023-05-16

Rust 创建泛型

// generic_function.rs
fn give_me<T>(value: T)  {
let  _ = value;
}

fn main() {   
 let a = "generics";   
 let b = 1024;   
 give_me(a);  
 give_me(b);
  }

泛型结构体

// generic_struct.rs

struct GenericStruct<T>(T);
struct Container<T> {   
 item: T
}

fn main() {    
// stuff
}

泛型枚举

// generic_enum.rs

enum Transmission<T> {   
 Signal(T),   
  NoSignal
}

fn main() {
    // stuff
 }

Rust 泛型实现

// generic_struct_impl.rs

struct Container<T> {  
  item: T
  }

impl<T>  Container<T> {    
    fn new(item: T) -> Self {    
             Container { item }  
      }
  }

fn main() {
 // stuff
 }

Rust 泛型应用

// using_generic_vec.rs

fn main() {   
 // 提供一种类型    
 let v1: Vec<u8> = Vec::new();
   // 或者调用某个方法    
   let mut v2 = Vec::new();    
   v2.push(2);        // 现在v2的类型是Vec<i32>   
    // 或者使用turbofish符号  
   let v3 = Vec::<u8>::new();      // 不是那么容易理解
  }

Rust 特征

关联方法:这些方法可以直接在实现特征的类型上使用,并不需要类型的实例来调用。在主流的编程语言中,这也被称为静态方法,例如标准库的特征FromStr的from_str方法。

实例方法:这些方法需要将self作为其第一个参数。这仅适用于实现特征的类型实例,self将指向实现特征的类型实例。

// super_player/src/main.rs

struct Audio(String);
struct Video(String);

impl Playable for Audio {    
            fn play(&self) {        
            println!("Now playing: {}", self.0);   
             }
  }

impl Playable for Video {    
             fn play(&self) {        
             println!("Now playing: {}", self.0);  
               }
}


fn main() { 
       println!("Super player!");
let audio = Audio("ambient_music.mp3".to_string());   
 let video = Video("big_buck_bunny.mkv".to_string());  
   audio.play();   
    video.play();
}

// super_player/src/media.rs

pub   trait Playable {    
        fn play(&self);    
        fn pause() {      
                  println!("Paused");   
           }
    }

// trait_inheritance.rs

trait Vehicle {    
       fn get_price(&self) -> u64;
       }
       
  trait Car: Vehicle {    
          fn model(&self) -> String;
    }

struct TeslaRoadster {    
          model: String,    
          release_date: u16
    }

impl   TeslaRoadster {    
fn new(model: &str, release_date: u16) -> Self {        
      Self { model: model.to_string(), release_date }    
      }
   }


impl Car for TeslaRoadster {   
            fn model(&self) -> String {        
            "Tesla Roadster I".to_string()  
              }
  }

impl Vehicle for TeslaRoadster {   
         fn get_price(&self) -> u64 {       
          200_000    
          }
   }

fn main() {    
let my_roadster = TeslaRoadster::new("Tesla Roadster II", 2020);    
println!("{} is priced at ${}", my_roadster.model,
my_roadster.get_price());
}

特征的多种形式

标记特征

简单特征

trait Foo { 
   fn foo();
   }

泛型特征

pub trait From<T> {   
 fn from(T) -> Self;
 }

关联类型特征

trait Foo {    
       type Out;    
       fn get_value(self) -> Self::Out;
}

继承特征

trait Bar {    
  fn bar();
}

trait Foo: Bar {
    fn foo();
}

使用包含泛型的特征——特征区间

struct Game;
struct Enemy;
struct Hero;

impl Game {   
         fn load<T>(&self, entity: T) {        
         entity.init();   
          }
    }

fn main() {   
 let game = Game;    
 game.load(Enemy);    
 game.load(Hero);
 }

必须在泛型声明旁边放置几个符号来指定特征 ,特征区间

struct Game;
struct Enemy;
struct Hero;

trait Loadable {    
        fn init(&self);
}

impl Loadable for Enemy {    
       fn init(&self) {        
            println!("Enemy loaded");   
            }
  }

impl  Loadable for Hero {    
        fn init(&self) {        
                println!("Hero loaded");  
        }
  }

impl Game {    
        fn load<T: Loadable>(&self, entity: T) {         // 特征区间
                 entity.init();    
                 }
    }

fn main() {    
      let game = Game;    
      game.load(Enemy);    
      game.load(Hero);
  }

使用标准库特征区间

use std::ops::Add;

fn add_thing<T: Add>(fst: T, snd: T) {    
   let _ = fst + snd;
}

fn main() {    
    add_thing(2, 2);
  }

区间内泛型

fn show_me<T: Display>(val: T) {   
 // 可以使用 {}格式化字符串, 因为有 Display特征区间   
  println!("{}", val);
  }

where语句

pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err> where F: FromStr { ... }

类型上的特征区间

use std::fmt::Display;

struct Foo<T: Display> {  
  bar: T
  }
// or
struct Bar<F> where F: Display {
 inner: F
 }

fn main() {}

泛型函数和impl代码块上的特征区间

use std::fmt::Debug;

trait Eatable {    
       fn eat(&self);
}

#[derive(Debug)]
struct Food<T>(T);

#[derive(Debug)]
struct Apple;

impl<T>  Eatable for Food<T> where T: Debug {    
             fn eat(&self) {        
             println!("Eating {:?}", self);  
               }
     }

fn eat<T>(val: T) where T: Eatable {    
          val.eat();
  }

fn main() {
    let apple = Food(Apple);   
    eat(apple);
 }

使用“+”将特征组合为区间

impl<K: Hash + Eq, V> HashMap<K, V, RandomState>

trait Eat {    
       fn eat(&self) {        
       println!("eat");  
         }
    }
    
trait Code {   
     fn code(&self) {        
     println!("code");   
      }
  }

trait Sleep {
       fn sleep(&self) {       
        println!("sleep"); 
           }
 }

trait Programmer : Eat + Code + Sleep {    
        fn animate(&self) {       
         self.eat();       
          self.code();        
          self.sleep();        
          println!("repeat!");   
           }
}

struct Bob;
impl Programmer for Bob {}
impl Eat for Bob {}
impl Code for Bob {}
impl Sleep for Bob {}

fn main() {
   Bob.animate();
}

特征区间与impl特征语法

声明特征区间的另一种语法是impl特征语法,它是编译器的最新特性

use std::fmt::Display;

fn show_me(val: impl Display) {    
       println!("{}", val);
  }

fn main() {    
     show_me("Trait bounds are awesome");
 }
fn lazy_adder(a:u32, b: u32) -> impl Fn() -> 
u32 {    
        move || a + b
}

fn main() {    
          let add_later = lazy_adder(1024, 2048);    
          println!("{:?}", add_later());
}
use std::fmt::Display;

fn surround_with_braces(val: impl Display) -> 
impl Display {    
        format!("{{{}}}", val)
}

fn main() {    
         println!("{}", surround_with_braces("Hello"));
 }

标准库特征简介

#[derive(Default)]
struct Complex<T> {   
 //实部   
  re: T,   
  //虚部    
  im: T
  }

impl<T> Complex<T> {    
              fn new(re: T, im: T) -> Self {       
               Complex { re, im } 
                  }
    }

#[cfg(test)]
mod tests {    
            use Complex;    
            #[test]    
            fn complex_basics() {       
             let first = Complex::new(3,5);        
             let second: Complex<i32> = Complex::default();        
             assert_eq!(first.re, 3);        
             assert_eq!(first.im, 5);        
             assert!(second.re == second.im);    
             }
    }

Debug 特征有助于在控制台上输出类型以便进行调试。
PartialEq和Eq:特征允许两个元素相互比较以验证是否相等。
Copy和Clone:特征定义了类型的复制方式。

#[derive(Default, Debug, PartialEq, Copy, Clone)]
struct Complex<T> {    
// 实部   
 re: T,   
 //虚部   
  im: T
  }

impl<T> Complex<T> {   
           fn new(re: T, im: T) -> Self {        
              Complex { re, im }   
           }
 }

impl<T: Add<T, Output=T>> Add for Complex<T> 
{   
     type Output = Complex<T>;    
      fn add(self, rhs: Complex<T>) -> Self::Output {  
            Complex { re: self.re + rhs.re, im: self.im + rhs.im }  
              }
}

#[cfg(test)]
mod tests {    
         use Complex;    
         #[test]    
         fn complex_basics() {        
         let first = Complex::new(3,5);        
         let second: Complex<i32> =
          Complex::default();    
}    

fn complex_addition() {        
          let a = Complex::new(1,-2);        
          let b = Complex::default();        
          let res = a + b;        
          assert_eq!(res, a);   
      }
 }
use std::convert::From;

impl<T> From<(T, T)> for Complex<T> {   
             fn from(value: (T, T)) -> Complex<T> {        
             Complex { re: value.0, im: value.1 }  
            }
}

// 其他impl代码块被省略了

#[cfg(test)]
mod tests {    
         // 其他测试     
         use Complex;
           #[test]     
           fn complex_from() {         
               let a = (2345, 456);        
               let complex = Complex::from(a);         
               assert_eq!(complex.re, 2345);        
               assert_eq!(complex.im, 456);  
           }
 }
// 为了表述简洁,前面的代码已经省略

use std::fmt::{Formatter, Display, Result};

impl<T: Display> Display for Complex<T> {    
         fn fmt(&self, f: &mut Formatter) ->
          Result {       
           write!(f, "{} + {}i", self.re, self.im)
              }
}

#[cfg(test)]
mod tests {    
   // other tests    
   use Complex;    
   #其他测试   
   fn complex_display() {        
          let my_imaginary = Complex::new(2345,456);       
          println!("{}", my_imaginary); 
     }
}

使用特征对象实现真正的多态性

use std::fmt::Debug;

#[derive(Debug)]
struct Square(f32);
#[derive(Debug)]
struct Rectangle(f32, f32);

trait Area: Debug {   
        fn get_area(&self) -> f32;
 }

impl Area for Square {    
       fn get_area(&self) -> f32 {      
         self.0 * self.0  
           }
}

impl  Area for Rectangle {    
       fn get_area(&self) -> f32 {        
       self.0 * self.1   
        }
  }

fn main() {   
       let shapes: Vec<&dyn Area> = vec![&Square(3f32), &Rectangle(4f32,2f32)];   
        for s in shapes {     
           println!("{:?}", s);   
            }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rust 类型、泛型和特征 的相关文章

随机推荐

  • Golang Map 基本原理

    Go 语言中的 map 即哈希表 哈希表把元素分到多个桶里 xff0c 每个桶里最多放8个元素 在访问元素时 xff0c 首先用哈希算法根据 key 和哈希表种子获得哈希值 暂将其命名为 h xff0c 然后利用 h 的低 b b b 位得
  • Go 汇编器指南

    A Quick Guide to Go s Assembler Go汇编器指南 This document is a quick outline of the unusual form of assembly language used b
  • [golang] 什么情况下reflect.IsValid 返回 false?

    https stackoverflow com questions 39011295 when does reflect isvalid return false 总结成一句话 xff1a IsValid 表示是否 Value 是否 wra
  • IPv6的DNS,设置DNS

    来自下一代互联网国家工程中心的最新消息 xff0c 该中心正式宣布推出IPv6公共DNS xff1a 240c 6666 xff0c 这是面向全球免费提供的公共DNS服务 同时 xff0c 还有一个备用DNS xff1a 240c 6644
  • MongoDB 查询包含某字符串的记录

    34 key 34 regex 广东
  • Anaconda使用conda连接网络出现错误(CondaHTTPError: HTTP 000 CONNECTION FAILED for url)

    进入 HOMEPATH 目录 编辑其中的 condarc 文件 删除 default 将 https 改成 http 转载自 Anaconda使用conda连接网络出现错误 CondaHTTPError HTTP 000 CONNECTIO
  • Win10 EFI启动文件被删的修复办法

    首先确保EFI分区存在 没有的话可以进入PE创建 首先是不成功的办法 xff1a 用PE里的EFI分区修复 xff0c 成功把Win7变成了EFI启动 xff08 以前梦寐以求的 xff09 xff0c 但是Win10一直修复失败 xff0
  • 关于UITabBarController的UITabBar隐藏问题

    最开始的时候我用的 void hideTabBar if self tabBarController tabBar hidden 61 61 YES return UIView contentView if self tabBarContr
  • NSAttributedString宽高计算小技巧

    通常对于CoreText之类自己实现绘制的控件来说 xff0c 计算富文本的宽高其实需要依赖CTFramesetterSuggestFrameSizeWithConstraints这个方法 但有些时候 xff0c 我们可能只是使用UILab
  • 拦截器获取HttpServletRequest里body数据

    一 问题 通过在拦截器中获取request中的json数据 xff0c 我们可以实现对参数进行校验和改写 问题是参数只能在拦截器里获取一次 xff0c 往后在controller层就无法获取数据 xff0c 提示body为空 在网上查找资料
  • iOS开发小技巧之--WeakSelf宏的进化

    我们都知道在防止如block的循环引用时 xff0c 会使用 weak关键字做如下定义 xff1a span class hljs keyword weak span typeof span class hljs keyword self
  • 用JavaScriptCore做android和iOS都兼容的JS-NativeSDK

    最近在给公司做一个JS Native的SDK xff0c 就是用于JS和原生之间的交互 使用场景上主要还是webView xff0c 那么原先的url拦截的方式已经不再考虑 xff0c 我们使用了iOS7之后的JavaScriptCore
  • 关于Xcode8 iOS10下模拟器NSLog不输出的问题

    昨天升级了Xcode8beta版 xff0c 兴高采烈的打开工程启动模拟器后发现自己的NSLog输出在console中看不到了 xff0c 查阅Xcode8 release note后发现官方的中有这么一段 When debugging a
  • ShareSDK 3.4.0 isWXAppInstalled 返回NO

    升级到3 4 0版本的ShareSDK之后 xff0c 发现 WXApi isWXAppInstalled 方法一直返回false xff0c 无法正常使用 初步怀疑是ShareSDK自己的bug 查找资料后发现 xff0c 解决方案居然是
  • iOS网络诊断功能 ping traceroute

    最近工作中总是遇到需要排查移动客户端网络状况的情况 xff0c 可能由于某些地区网络运营商的问题 xff0c 导致客户端某些功能不正常 xff0c 现在的做法也是非常麻烦的 xff1a 某用户反馈某一功能不能用由运营联系到该用户运营指导该用
  • macOS10.12下如何丝滑的使用appium?

    appium是一个自动化测试的跨平台解决方案 xff0c 这篇文章针对最新版的xcode 8 2和mac OS 10 12给出基本完成的部署过程 xff0c 值得一看 实际操作过程中 xff0c 有几个地方需要注意 xff1a 不要忘记启动
  • iOS如何在页面销毁时优雅的cancel网络请求

    大家都知道 xff0c 当一个网络请求发出去之后 xff0c 如果不管不顾 xff0c 有可能出现以下情况 xff1a 进入某个页面 xff0c 做了某种操作 xff08 退出页面 切换某个tab等等 xff09 导致之前的请求变成无用请求
  • glibc源码解读——malloc

    通过宏定义的展开 xff0c 找到malloc的函数地址 xff1a define C SYMBOL NAME name name define ASM LINE SEP void libc malloc size t bytes libc
  • 音视频开发入门基础知识(视频入门篇)

    RTSP实时音视频开发实战课程 xff1a lt RTSP实时音视频开发实战 gt 音视频开发入门基础知识 xff08 音频入门篇 xff09 目录 一 前言 二 视频采集和显示 三 视频常见的格式 四 RGB转YUV和YUV转RGB 五
  • Rust 类型、泛型和特征

    Rust 创建泛型 generic function rs fn give me lt T gt value T let 61 value fn main let a 61 34 generics 34 let b 61 1024 give