写点什么

Rust 的对象安全性

作者:Shine
  • 2022 年 4 月 04 日
  • 本文字数:629 字

    阅读完需:约 2 分钟

能够用在动态指派的 trait 称作 trait 对象, 表现为参数形式为 dyn trait. trait 与面向对象世界中的 interface 含义不同,不是所有的 trait 都能用于多态.下面两个 trait 就不能用于多态:

  1. Clone 不能转变成 trait 对象, 因为 clone 方法返回 Self. 如果有个方法能够接受 dyn Clone 参数, 当调用 clone 方法,由于 clone 方法返回 Self, 编译器我无法知道具体的返回类型.

pub trait Clone {    fn clone(&self) -> Self;    fn clone_from(&mut self, source: &Self) { ... }}
复制代码
  1. Extend trait 不能用作 trait 对象, 因为 extend 方法有泛型参数. 如果我们调用 extend 方法, 在虚方法表中有多个 extend 的地址, 我们无法知道调用哪个.

非对象安全的 trait 不能够

pub trait Extend<A> {    fn extend<T>(&mut self, iter: T)    where        T: IntoIterator<Item = A>;
fn extend_one(&mut self, item: A) { ... } fn extend_reserve(&mut self, additional: usize) { ... }}
复制代码


能用做 trait 对象的 trait 称作对象安全的(object-safe)trait. 一个 object-safe 的 trait, 其中的方法不能带泛型参数, 或者使用 Self 类型. 此外, 对象安全的 trait 不能有静态方法(第一个参数不能解引用为 Self)

使用 Self:Sized 约束的 trait 也不能用作 trait 对象. 可以将 Self:Sized 约束在 trait 的某个方法上, 该方法不能用于动态指派, 但是该 trait 本身还是对象安全的. 如果 trait 的某个方法有泛型参数,可以将该方法带上 Self:Sized 约束, 以保留这个 trait 的对象安全性.

如果实现 trait 的类型有种,考虑保留 trait 的对象安全性.


用户头像

Shine

关注

万物负阴而抱阳,冲气以为和 2017.11.23 加入

一名修身养性的程序员

评论

发布
暂无评论
Rust的对象安全性_rust_Shine_InfoQ写作平台