![](/img/trans.png)
[英]Can't implement a trait I don't own for all types that implement a trait I do own
[英]How do I implement a trait I don't own for a type I don't own?
我想为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 和类型 [E0117]
或者
类型参数
T
必须用作某些本地类型的类型参数(例如MyStruct<T>
); 只能为类型参数实现当前 crate 中定义的特征 [E0210]
据我了解,我必须修补 stdlib,更具体地说是collections::vec
板条箱。 是否有另一种方法可以更改此代码以成功编译?
虽然您不能完全做到这一点,但通常的解决方法是将您想要的类型包装在您自己的类型中并在其上实现特征。
use somecrate::FooType;
use somecrate::BarTrait;
struct MyType(FooType);
impl BarTrait for MyType {
fn bar(&self) {
// use `self.0` here
}
}
这将使像
vec << 4
这样的东西成为可能,这对vec.push(4)
来说是很好的糖。
虽然可以做到,但实现具有意外语义的运算符通常是一个 坏主意。
以下是如何做到这一点的示例:
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)
}
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,它可以为你生成一些样板代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.