如何为我不拥有的类型实现我不拥有的特征?
Posted
技术标签:
【中文标题】如何为我不拥有的类型实现我不拥有的特征?【英文标题】:How do I implement a trait I don't own for a type I don't own? 【发布时间】:2014-10-14 07:28:53 【问题描述】:我想为Vec
实现Shl
特征,代码如下。这将使vec << 4
之类的事情成为可能,这对vec.push(4)
来说是很好的糖。
use std::ops::Shl;
impl<T> Shl<T> for Vec<T>
type Output = Vec<T>;
fn shl(&self, elem: &T) -> Vec<T>
self.push(*elem);
*self
fn main()
let v = vec![1, 2, 3];
v << 4;
编译失败并出现以下错误:
无法提供扩展实现,其中 trait 和类型都未在此 crate 中定义 [E0117]
或
类型参数
T
必须用作某些本地类型的类型参数(例如MyStruct<T>
);类型参数只能实现当前 crate 中定义的特征 [E0210]
据我了解,我必须修补 stdlib,更具体地说是 collections::vec
板条箱。是否有其他方法可以更改此代码以成功编译?
【问题讨论】:
这在设计上是不可能的。 【参考方案1】:虽然您不能完全做到这一点,但通常的解决方法是将您想要的类型包装在您自己的类型中并在其上实现特征。
use somecrate::FooType;
use somecrate::BarTrait;
struct MyType(FooType);
impl BarTrait for MyType
fn bar(&self)
// use `self.0` here
【讨论】:
附录:实现 Deref trait 以避免每次都输入<MyType>.0.foo
这在 2020 年仍然有效吗?
@max 是的。这种“限制”是使 rust 成为如此好的语言的核心因素之一。所以这在 2020 年仍然有效,并且在 Rust 版本 1 中可能永远有效。【参考方案2】:
这将使
vec << 4
之类的事情成为可能,这对vec.push(4)
来说是很好的糖。
虽然可以做到,但一般是bad idea来实现一个意外语义的算子。
以下是如何做到这一点的示例:
use std::ops::Shl;
struct BadVec<T>(Vec<T>);
impl<T> Shl<T> for BadVec<T>
type Output = BadVec<T>;
fn shl(mut self, elem: T) -> Self::Output
self.0.push(elem);
self
fn main()
let mut v = BadVec(vec![1, 2, 3]);
v = v << 4;
assert_eq!(vec![1, 2, 3, 4], v.0)
如果你实现Deref
(DerefMut
):
use std::ops::Deref, DerefMut;
impl<T> Deref for BadVec<T>
type Target = Vec<T>;
fn deref(&self) -> &Self::Target
&self.0
impl<T> DerefMut for BadVec<T>
fn deref_mut(&mut self) -> &mut Self::Target
&mut self.0
你可以调用Vec
方法:
fn main()
let mut v = BadVec(vec![1, 2, 3]);
v = v << 4;
v.truncate(2);
assert_eq!(2, v.len());
看看newtype_derive
crate,它可以为你生成一些样板代码。
【讨论】:
以上是关于如何为我不拥有的类型实现我不拥有的特征?的主要内容,如果未能解决你的问题,请参考以下文章