0

目标是拥有类似于(游乐场)的东西:

trait T {
    fn get_mutable_attribute(&mut self) -> &mut String;
    fn forwardable_append_attribute(mut self, new_value: &str) -> Self {
        let attribute = self.get_mutable_attribute();
        attribute.push_str(new_value);
        println!("{}", attribute);
        self
    }
}

struct S {
    attribute: String,
}

impl T for S {
    fn get_mutable_attribute(&mut self) -> &mut String {
        &mut self.attribute
    }
}

fn main() {
    let s = S {
        attribute: "init".to_string(),
    }
    .forwardable_append_attribute("new_1")
    .forwardable_append_attribute("new_2")
    .forwardable_append_attribute("new_3");
}

这给出了错误:

error[E0277]: the size for values of type `Self` cannot be known at compilation time
 --> src/main.rs:3:37
  |
3 |     fn forwardable_append_attribute(mut self, new_value: &str) -> Self {
  |                                     ^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: unsized locals are gated as an unstable feature
help: consider further restricting `Self`
  |
3 |     fn forwardable_append_attribute(mut self, new_value: &str) -> Self where Self: std::marker::Sized {
  |                                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: function arguments must have a statically known size, borrowed types always have a known size
  |
3 |     fn forwardable_append_attribute(&mut self, new_value: &str) -> Self {
  |                                     ^

另一种方法是为实现特征的每个对象定义特征方法,但这会在所有子对象(操场)之间引入重复:

trait T {
    fn get_mutable_attribute(&mut self) -> &mut String;
    fn forwardable_append_attribute(self, new_value: &str) -> Self;
}

struct S {
    attribute: String,
}

impl T for S {
    fn get_mutable_attribute(&mut self) -> &mut String {
        &mut self.attribute
    }
    fn forwardable_append_attribute(mut self, new_value: &str) -> Self {
        let attribute = self.get_mutable_attribute();
        attribute.push_str(new_value);
        println!("{}", attribute);
        self
    }
}

fn main() {
    let s = S {
        attribute: "init".to_string(),
    }
    .forwardable_append_attribute("new_1")
    .forwardable_append_attribute("new_2")
    .forwardable_append_attribute("new_3");
}
4

1 回答 1

3

它抱怨你不能回来self,因为self可能不会Sized因此,您可以只添加一个Self必须Sized在方法上的边界:

trait T {
    fn get_mutable_attribute(&mut self) -> &mut String;
    fn forwardable_append_attribute(mut self, new_value: &str) -> Self
    // note this trait bound
    where
        Self: Sized,
    {
        let attribute = self.get_mutable_attribute();
        attribute.push_str(new_value);
        println!("{}", attribute);
        self
    }
}

struct S {
    attribute: String,
}

impl T for S {
    fn get_mutable_attribute(&mut self) -> &mut String {
        &mut self.attribute
    }
}

fn main() {
    let s = S {
        attribute: "init".to_string(),
    }
    .forwardable_append_attribute("new_1")
    .forwardable_append_attribute("new_2")
    .forwardable_append_attribute("new_3");
}

请注意,您也可以将Sized边界放在特征本身而不是方法上,看起来像trait T: Sized {...}. 如果 trait 只提供可链接方法,则应该这样做,因此为不能具有可链接方法的类型实现特征是没有意义的。或者,self您可以获取可变引用并返回可变引用,而不是进入函数,而无需Sized

trait T {
    fn get_mutable_attribute(&mut self) -> &mut String;
    // note the &mut self and &mut Self
    fn forwardable_append_attribute(&mut self, new_value: &str) -> &mut Self {
        let attribute = self.get_mutable_attribute();
        attribute.push_str(new_value);
        println!("{}", attribute);
        self
    }
}

struct S {
    attribute: String,
}

impl T for S {
    fn get_mutable_attribute(&mut self) -> &mut String {
        &mut self.attribute
    }
}

fn main() {
    let s = S {
        attribute: "init".to_string(),
    }
    .forwardable_append_attribute("new_1")
    .forwardable_append_attribute("new_2")
    .forwardable_append_attribute("new_3");
}
于 2020-11-16T13:31:40.843 回答