如何编写一个具有返回引用的方法并正确实现它的特征?

时间:2016-11-06 12:47:19

标签: rust

我想编写一个具有trait GetRef<'a> { fn get(&self) -> &'a u8; } // U8Ref works fine struct U8Ref<'a> { data: &'a u8 } impl<'a> GetRef<'a> for U8Ref<'a> { fn get(&self) -> &'a u8 { self.data } } struct U80 { data: u8 } struct U81 { data: u8 } struct U82 { data: u8 } struct U83 { data: u8 } // works, but is not exactly what I want (API changes, and does not work on // &mut U80, see main() below) impl<'a> GetRef<'a> for &'a U80 { fn get(&self) -> &'a u8 { &self.data } } impl<'a> GetRef<'a> for U81 { fn get(&self) -> &'a u8 { // E0495: cannot infer an appropriate lifetime for lifetime parameter // in generic type due to conflicting requirements &self.data } } impl<'a> GetRef<'a> for U82 { //E0308: lifetime mismatch fn get(&'a self) -> &'a u8 { &self.data } } impl<'a> GetRef<'a> for &'a mut U83 { fn get(&self) -> &'a u8 { // again E0495 &self.data } } fn main() { let u0 = U80 {data :0}; // works (&u0).get(); // no method named `get` found for type `U80` in the current scope u0.get(); // no method named `get` found for type `&mut U80` in the current scope (&mut u0).get(); } 方法的特征,并将其实现为具体类型而不是引用。这是我尝试过的,但我无法让它发挥作用:

float floatValue = 2.7f;
int value = (int)floatValue;
System.out.println(value); // 2

2 个答案:

答案 0 :(得分:2)

首先,您应指定&self与返回值具有相同的生命周期(两者都在实现中的特征中)。否则,编译器会正确地告诉您该值可能不够长。

其次,您应该impl类型本身的特征,而不是对类型的引用。如果您在impl Trait for &'a U80内写&selfimpl内的&&U80将会有U80类型,这不是您想要的。实现U80的特征将使特征方法同时适用于&U80&mut U80&self,因为特征方法会收到trait GetRef<'a> { fn get(&'a self) -> &'a u8; } struct U8Ref<'a> { data: &'a u8 } impl<'a> GetRef<'a> for U8Ref<'a> { fn get(&self) -> &'a u8 { self.data } } struct U80 { data: u8 } impl<'a> GetRef<'a> for U80 { fn get(&'a self) -> &'a u8 { &self.data } } fn main() { let mut u0 = U80 {data :0}; (&u0).get(); u0.get(); (&mut u0).get(); }

object2

答案 1 :(得分:2)

您的特质的实现需要限制所涉及的生命周期。对于exec('convert -units \'PixelsPerInch\' -density 150 '.$filename.'.png '.$filename.'.pdf'); 个案,生命周期将超过U8Ref,但在self和类似情况下,他们将是平等的。

特质需要有两个生命周期作为输入才能表达这一点,所以让我们将U80生命周期添加为self

's

现在这些是明确的,我们可以写trait GetRef<'a, 's> { fn get(&'s self) -> &'a u8; } 。首先,对于持有参考的那个:

impl

现在对于之前更难的情况,我们可以明确地告诉编译器生命周期是相同的:

struct U8Ref<'a> {
    data: &'a u8
}

// Straightforward; we can separate the self and return reference lifetimes.
impl<'a, 's> GetRef<'a, 's> for U8Ref<'a> {
    fn get(&'s self) -> &'a u8 {
        self.data
    }
}

用它来检查它编译:

struct U80 { data: u8 }

// The impl is only valid when &self has the same lifetime as the &u8 returned.
impl<'a> GetRef<'a, 'a> for U80 {
    fn get(&'a self) -> &'a u8 {
        &self.data
    }
}

Playground link