Rust Trait 接口

发布时间: 更新时间: 总字数:1079 阅读时间:3m 作者: IP上海 分享 网址

Rust中Trait用来定义某种类型具有哪些并且可以与其他类型共享的功(或行为)

介绍

Trait 本意为特点,与其他语言的 接口(interface) 相似,但也有不同。

Trait bounds(约束):泛型类型参数指定为实现了特定行为的类型。

定义 Trait

Trait 是把方法签名放在一起,来定义实现某种目的所必需的一组行为。Trait 特征如下:

  • 使用 trait 关键字定义
  • 只有方法签名,没有具体实现,多个方法以 ; 结尾
  • 实现 trait 必需提供具体的方法实现
pub trait Trait名称 {
    fn 方法名1(&self) -> 返回值1;
    fn 方法名2(参数...) -> 返回值2;
    ...
}

实现 Trait

impl Trait名称 for 结构体名称.. {
    fn 方法名1(&self) -> 返回值1 {
        ...
    }
    fn 方法名2(参数...) -> 返回值2 {
        ...
    }
    ...
}

说明:

  • Trait 的方法需要在 impl 代码块里对方法签名进行实现
pub trait Summary {
  fn summary(&self) -> String;
}

pub struct BlogPost {
  pub title: String,
  pub author: String,
  pub content: String,
}

impl Summary for BlogPost {
  fn summary(&self) -> String {
      format!("{} by {}", self.title, self.author)
  }
}

fn main() {
  let p = BlogPost {
      title: String::from("some title"),
      author: String::from("xiexianbin"),
      content: String::from("abcd23"),
  };

  println!("{}", p.summary())
}

实现 trait 的约束:

  • 某类型实现 trait 的前提条件:该类型或该 trait 是在本地 crate 里定义的
  • 无法为外部类型来实现外部的 trait,如无法在标准库外为某个类型实现 Display trait
  • Trait 可以加默认实现,该实现可以重写,若需要采用默认实现,impl 块中不需要添加具体实现
    • 默认实现可以调用 trait 中其他的方法,即使该方法没有默认实现也可以
    • 无法在重写实现中调用默认实现,即不支持其他语言的 supper.方法() 调用
pub trait Summary {
  fn summary(&self) -> String {
      format!("some thing...")
  }
}

pub struct BlogPost {
  pub title: String,
  pub author: String,
  pub content: String,
}

impl Summary for BlogPost {
}

fn main() {
  let p = BlogPost {
      title: String::from("some title"),
      author: String::from("xiexianbin"),
      content: String::from("abcd23"),
  };

  println!("{}", p.summary())
}

Trait 作为参数

实现方式:

  • 使用 impl Trait名称 作为参数:简单情况
  • 使用 trait bound 语法:复杂情况
    • impl trait 语法是 trait bound 的语法糖
  • 使用 + 指定多个 trait bound,如:
    • pub fn summary3(i: impl Summary + Display) {}
    • pub fn summary4<T: Summary + Display>(i: T) {}
  • trait bound 使用 where 子句,解决上面展示复杂问题
    • 在方法签名后指定 where 子句
use std::fmt::{Display, Debug};

pub trait Summary {
    fn summary(&self) -> String;
}

pub struct BlogPost {
    pub title: String,
    pub author: String,
    pub content: String,
}

impl Summary for BlogPost {
    fn summary(&self) -> String {
        format!("{} by {}", self.title, self.author)
    }
}

// 简单写法
//pub fn summary1(i: &impl Summary) {
pub fn summary1(i: impl Summary) {
    println!("{}", i.summary())
}

// trait bound 语法
//pub fn summary2<T: Summary>(i: &T) {
pub fn summary2<T: Summary>(i: T) {
    println!("{}", i.summary())
}

// 实现多个 trait
pub fn summary3(i: impl Summary + Display) {
    println!("{}", i.summary())
}

pub fn summary4<T: Summary + Display>(i: T) {
    println!("{}", i.summary())
}

// where 子句,类似于 c# 的写法
pub fn summary5<T, U>(x: T, y: U) -> String
where
    T: Summary + Display,
    U: Debug,
{
    format!("{}", x.summary())
}

fn main() {
    let p = BlogPost {
        title: String::from("some title"),
        author: String::from("xiexianbin"),
        content: String::from("abcd23"),
    };

    // summary1(p);
    summary2(p);
}

Trait 作为返回类型

  • impl Trait 语法
    • impl Trait 只能返回确定的同一种类型,返回多种类型会报错
pub trait Summary {
  fn summary(&self) -> String;
}

pub struct BlogPost {
  pub title: String,
  pub author: String,
  pub content: String,
}

impl Summary for BlogPost {
  fn summary(&self) -> String {
      format!("{} by {}", self.title, self.author)
  }
}

// 只能返回特定类型
pub fn new_blog_post(title: String, author: String, content: String) -> impl Summary {
  BlogPost {
      title,
      author,
      content,
  }
}

fn main() {
  let p = new_blog_post(
      String::from("some title"),
      String::from("xiexianbin"),
      String::from("abcd23"));
  println!("{}", p.summary());
}

其他

  • 在使用泛型类型参数的 impl 块上使用 trait bound,我们可以有条件的为实现了特定 trait 的类型来实现方法
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数