首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为实现特性的类型实现Borrow<Trait>

为实现特性的类型实现Borrow<Trait>
EN

Stack Overflow用户
提问于 2016-04-07 01:14:29
回答 2查看 3.2K关注 0票数 9

假设我有一些特质:

代码语言:javascript
复制
trait MyTrait {
    fn function1(&self);
}

以及实现它的某种类型:

代码语言:javascript
复制
struct MyStruct {
    number: i32,
}
impl MyTrait for MyStruct {
    fn function1(&self) {
        printn!("{}", self.number);
    }
}

现在我有了另一种类型,它想要使用实现MyTrait的东西。不管他们是否拥有。从阅读中可以看出,实现这一目标的正确方法是让它使用Borrow<X>,而不是X&X或其他什么。这让它可以使用X类型的东西,或者Rc<X>或者Box<X>,等等.

X是一种具体的类型时,我已经做到了这一点,但是当X是一种特性时,我如何使它工作呢?

以下是我第一次尝试的:

代码语言:javascript
复制
struct Consumer<T> {
    inner: T
}

impl<T: Borrow<MyTrait>> Consumer<T> {
    pub fn new(inner: T) -> Consumer<T> {
        Consumer {
            inner: inner
        }
    }
    pub fn do_stuff(&self) {
        self.inner.borrow().function1();
    }
}

fn main() {
    // I want to eventually be able to swap this out for x = Rc::new(MyStruct ...
    // but I'll keep it simple for now.
    let x = MyStruct { number: 42 };
    let c = Consumer::new(x);
    c.do_stuff();
}

这还不起作用,因为MyStruct实现了Borrow<MyStruct>,但没有实现Borrow<MyTrait>。好吧,让我们试着实现它:

代码语言:javascript
复制
impl Borrow<MyTrait> for MyStruct {
    fn borrow(&self) -> &MyTrait {
        self
    }
}

这给了我以下错误,我不明白:

:33:5 : 35 :6错误:方法borrow有一种不兼容的特性类型:期望绑定生存期参数,找到具体的生存期E0053 :33 fn借用(& self ) ->和MyTrait{ :34 self:35} :33:5: 35:6帮助:参见关于E0053错误的详细说明:由于以前的错误剧本而中止:应用程序以错误代码101终止

什么?这里根本没有提到任何具体的生命周期,而且Borrow也是在没有提到任何生命周期的情况下定义的。我很困惑。

首先,我的假设正确吗?使用Borrow是正确的选择吗?如果是这样的话,我如何实现一个特征的Borrow

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-07 01:26:25

编写实现的正确方法是:

代码语言:javascript
复制
impl<'a> Borrow<MyTrait + 'a> for MyStruct {
    fn borrow(&self) -> &(MyTrait + 'a) {
        self
    }
}

特征对象可以使用生存期绑定进行限制。这是因为实现特征的类型可能包含引用,在某些情况下,我们需要能够区分依赖于借来对象的对象和不依赖于借来对象的对象。如果没有指定生存期范围,我认为它默认为'static;但是,将&(MyTrait + 'static)指定为返回类型编译(它不那么泛型,因此您应该倾向于上面的泛型解决方案),所以您遇到的问题比.

票数 7
EN

Stack Overflow用户

发布于 2016-04-07 03:55:16

顺便说一下,我找到了一种替代的方法,这根本不需要实现Borrow<MyTrait>

impl<T: Borrow<MyTrait> Consumer<T>不同,我们可以让Consumer接受一个额外的参数,该参数指示实际借用的类型是什么,然后约束该类型来实现该特性。如下所示:

代码语言:javascript
复制
impl<T: Borrow<Borrowed>, Borrowed: MyTrait> Consumer<T, Borrowed> {

这要求Consumer有一个引用其他未使用的Borrowed类型参数的PhantomData成员。以下是一个完整的实现:

代码语言:javascript
复制
struct Consumer<T, Borrowed> {
    inner: T,
    phantom: PhantomData<Borrowed>
}

impl<T: Borrow<Borrowed>, Borrowed: MyTrait> Consumer<T, Borrowed> {
    fn new(inner: T) -> Consumer<T, Borrowed> {
        Consumer {
            inner: inner,
            phantom: PhantomData
        }
    }
    pub fn do_stuff(&self) { // this function is the same as before.
        self.inner.borrow().function1();
    }
}

这个选项具有一个很好的属性,它允许在其中使用带有泛型方法的特征,因为它不需要创建任何特征对象(不能为具有泛型函数的特征创建特征对象:请参见https://doc.rust-lang.org/error-index.html#method-has-generic-type-parameters)。

缺点之一是,Consumer现在必须得到有关其泛型参数的提示。你必须告诉它所涉及的具体类型:

代码语言:javascript
复制
fn main() {
    let x = MyStruct { number: 42 };
    let c = Consumer::<_, MyStruct>::new(x);
    c.do_stuff();
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36465009

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档