Rust 的对象安全性
能够用在动态指派的 trait 称作 trait 对象, 表现为参数形式为 dyn trait. trait 与面向对象世界中的 interface 含义不同,不是所有的 trait 都能用于多态.下面两个 trait 就不能用于多态:
Clone 不能转变成 trait 对象, 因为 clone 方法返回 Self. 如果有个方法能够接受 dyn Clone 参数, 当调用 clone 方法,由于 clone 方法返回 Self, 编译器我无法知道具体的返回类型.
复制代码
Extend trait 不能用作 trait 对象, 因为 extend 方法有泛型参数. 如果我们调用 extend 方法, 在虚方法表中有多个 extend 的地址, 我们无法知道调用哪个.
非对象安全的 trait 不能够
复制代码
能用做 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 的对象安全性.
评论