rust trait 学习笔记

参考: https://rustmagazine.github.io/rust_magazine_2021/chapter_7/rusts-standard-library-traits.html

0x01 trait 的默认方法

trait 和java 的interface 理解起来比较接近。

struct SomeType07;
struct OtherType07;
impl Trait07 for SomeType07 {}
impl Trait07 for OtherType07 {
    fn method(&self) {
        info!("other type 07 method");
    }
}

fn main() {
    tracing_subscriber::fmt().init();

    SomeType07.method();
    OtherType07.method();
}

0x02 给系统类型添加方法

可以为 i32、String 这类系统类型添加自定义的方法,便于使用

trait Trait08 {
    fn is_even(&self) -> bool;
}

impl Trait08 for u32 {
    fn is_even(&self) -> bool {
        self % 2 == 0
    }
}

fn main() {
    tracing_subscriber::fmt().init();
    let a = 19_u32;
    info!("{} is even: {}", a, a.is_even());
}

0x03 关于继承

结论就是不要使用继承,因为它不是覆盖
心智负担太重 -_-!

trait Trait09 {
    fn say_hello(&self) {
        info!("trait 09 say_hello");
    }
}

trait Trait10: Trait09 {}

0x04 trait 对象

trait 用于编译阶段,而trait 对象主要提供运行时多态能力。
trait 对象是一个指针,它没有大小。使用关键字 dyn

fn example(condition: bool, vec: Vec<i32>) -> Box<dyn Iterator<Item = i32>> {
    let iter = vec.into_iter();
    if condition {
        Box::new(iter.map(|x| x * 2))
    } else {
        Box::new(iter.filter(|&n| n >= 2))
    }
}

常见用法:

trait Trait {}

&dyn Trait
Box<dyn Trait>
Rc<dyn Trait>
Arc<dyn Trait>

0x05 标记 trait

不包含方法体的空trait ,用于“标记”某个属性

trait BlankTrait{}

0x06 Send ,Sync

线程安全的数据标识。

0x07 Sized

类型大小在编译期可知

0x08 Clone/Copy

会产生复制动作,性能占用较大

0x09 Any

动态参数化的实现手段,通过 match type_id 进行匹配

trait Any: 'static {
    fn type_id(&self) -> TypeId;
}


fn map_any(mut any: Box<dyn Any>) -> Box<dyn Any> {
    if let Some(num) = any.downcast_mut::<i32>() {
        *num += 1;
    } else if let Some(string) = any.downcast_mut::<String>() {
        *string += "!";
    } else if let Some(point) = any.downcast_mut::<Point>() {
        point.inc();
    }
    any
}

0x10 格式化 trait

Trait   Placeholder Description
--------------------------------------------------
Display {}  显示表示
Debug   {:?}    调试表示
Octal   {:o}    八进制表示
LowerHex    {:x}    小写十六进制表示
UpperHex    {:X}    大写十六进制表示
Pointer {:p}    内存地址
Binary  {:b}    二进制表示
LowerExp    {:e}    小写指数表示
UpperExp    {:E}    大写指数表示

0x11 转化为 String 的方式: Display & ToString

trait ToString {
    fn to_string(&self) -> String;
}

0x12 运算符重载

可以对 struct 增加运行符逻辑

Trait(s)    分类(Category)    操作符(Operator(s))    描述(Description)
Add 算术  +   相加
AddAssign   算术  +=  相加并赋值
BitAnd  算术  &   按位与
BitAndAssign    算术  &=  按位与并赋值
BitXor  算术  ^   按位异或
BitXorAssign    算术  ^=  按位异或并赋值
Div 算术  /   除
DivAssign   算术  /=  除并赋值
Mul 算术  *   乘
MulAssign   算术  *=  乘并赋值
Neg 算术  -   一元求反
Not 算术  !   一元逻辑求反
Rem 算术  %   求余
RemAssign   算术  %=  求余并赋值
Shl 算术  <<  左移
ShlAssign   算术  <<= 左移并赋值
Shr 算术  >>  右移
ShrAssign   算术  >>= 右移并赋值
Sub 算术  -   减
SubAssign   算术  -=  减并赋值

使用例:

#[derive(Clone, Copy)]
struct Point {
    x: i32,
    y: i32,
}

impl Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> Point {
        Point {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}

fn main() {
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 3, y: 4 };
    let p3 = p1 + p2;
    assert_eq!(p3.x, p1.x + p2.x); // ✅
    assert_eq!(p3.y, p1.y + p2.y); // ✅
}

0x13 闭包 trait


Trait(s)    分类(Category)    操作符(Operator(s))    描述(Description)
Fn  闭包  (...args)   不可变闭包调用
FnMut   闭包  (...args)   可变闭包调用
FnOnce  闭包  (...args)   一次性闭包调用

0x14 其他 trait

仅作用于 &变量

image.png


#![allow(unused)]
fn main() {
use std::ops::Deref;

struct Human {
    health_points: u32,
}

enum Weapon {
    Spear,
    Axe,
    Sword,
}

// a Soldier is just a Human with a Weapon
struct Soldier {
    human: Human,
    weapon: Weapon,
}

impl Deref for Soldier {
    type Target = Human;
    fn deref(&self) -> &Human {
        &self.human
    }
}

enum Mount {
    Horse,
    Donkey,
    Cow,
}

// a Knight is just a Soldier with a Mount
struct Knight {
    soldier: Soldier,
    mount: Mount,
}

impl Deref for Knight {
    type Target = Soldier;
    fn deref(&self) -> &Soldier {
        &self.soldier
    }
}

enum Spell {
    MagicMissile,
    FireBolt,
    ThornWhip,
}

// a Mage is just a Human who can cast Spells
struct Mage {
    human: Human,
    spells: Vec<Spell>,
}

impl Deref for Mage {
    type Target = Human;
    fn deref(&self) -> &Human {
        &self.human
    }
}

enum Staff {
    Wooden,
    Metallic,
    Plastic,
}

// a Wizard is just a Mage with a Staff
struct Wizard {
    mage: Mage,
    staff: Staff,
}

impl Deref for Wizard {
    type Target = Mage;
    fn deref(&self) -> &Mage {
        &self.mage
    }
}

fn borrows_human(human: &Human) {}
fn borrows_soldier(soldier: &Soldier) {}
fn borrows_knight(knight: &Knight) {}
fn borrows_mage(mage: &Mage) {}
fn borrows_wizard(wizard: &Wizard) {}

fn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {
    // all types can be used as Humans
    borrows_human(&human);
    borrows_human(&soldier);
    borrows_human(&knight);
    borrows_human(&mage);
    borrows_human(&wizard);
    // Knights can be used as Soldiers
    borrows_soldier(&soldier);
    borrows_soldier(&knight);
    // Wizards can be used as Mages
    borrows_mage(&mage);
    borrows_mage(&wizard);
    // Knights & Wizards passed as themselves
    borrows_knight(&knight);
    borrows_wizard(&wizard);
}

0x14 转换 trait ( From & Into)

不同类型之间相间转换


#![allow(unused)]
fn main() {
struct Point {
    x: i32,
    y: i32,
}

impl From<(i32, i32)> for Point {
    fn from((x, y): (i32, i32)) -> Self {
        Point { x, y }
    }
}

impl From<[i32; 2]> for Point {
    fn from([x, y]: [i32; 2]) -> Self {
        Point { x, y }
    }
}

fn example() {
    // 使用 From
    let origin = Point::from((0, 0));
    let origin = Point::from([0, 0]);

    // 使用 Into
    let origin: Point = (0, 0).into();
    let origin: Point = [0, 0].into();
}

0x15 Error Handling

生产开发中,已经转换为 anyhow, thiserror 处理异常了。

0x16 AsRef & AsMut

在函数内部获取参数的所有权


fn take_as_ref_str<T: AsRef<str>>(s: T) {
    let p: &str = s.as_ref();
    info!("take_as_ref_str {}", p);
}

fn main() {
    tracing_subscriber::fmt().init();

    let val = "中国".to_string();
    take_as_ref_str(val);
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容