实现Rust特征会导致找不到struct

时间:2014-08-29 07:37:29

标签: struct rust traits

当我在Rust中的结构上实现特征时,它导致找不到结构类型。首先,工作代码:

trait SomeTrait {
  fn new() -> Box<SomeTrait>;
  fn get_some_value(&self) -> int;
}

struct SomeStruct {
  value: int
}

impl SomeStruct {
  fn new() -> Box<SomeStruct> {
    return box SomeStruct { value: 3 };
  }

  fn get_some_value(&self) -> int {
    return self.value;
  }
}

fn main() {
  let obj = SomeStruct::new();
  println!("{}", obj.get_some_value());
}

这里没有使用SomeTrait特征。一切正常。如果我现在改变SomeStruct的impl来实现SomeTrait:

trait SomeTrait {
  fn new() -> Box<SomeTrait>;
  fn get_some_value(&self) -> int;
}

struct SomeStruct {
  value: int
}

impl SomeTrait for SomeStruct {
  fn new() -> Box<SomeTrait> {
    return box SomeStruct { value: 3 };
  }

  fn get_some_value(&self) -> int {
    return self.value;
  }
}

fn main() {
  let obj = SomeStruct::new();
  println!("{}", obj.get_some_value());
}

我收到错误:

trait.rs:21:13: 21:28 error: failed to resolve. Use of undeclared module `SomeStruct`
trait.rs:21   let obj = SomeStruct::new();
                        ^~~~~~~~~~~~~~~
trait.rs:21:13: 21:28 error: unresolved name `SomeStruct::new`.
trait.rs:21   let obj = SomeStruct::new();

我做错了什么?为什么SomeStruct突然失踪?谢谢!

1 个答案:

答案 0 :(得分:1)

目前,通过特征调用特征中的相关函数(非方法函数),即SomeTrait::new()。但是,如果你只是写这个,那么编译器就无法解决你正在使用的 ,因为没有办法指定SomeStruct信息(它只能起作用)如果签名中某处提到了特殊的Self类型。也就是说,编译器需要能够确定应该调用哪个版本的new。 (这是必需的;它们可能有非常不同的行为:

struct Foo;
impl SomeTrait for Foo {
    fn new() -> Box<SomeTrait> { box Foo as Box<SomeTrait> }
}

struct Bar;
impl SomeTrait for Bar {
    fn new() -> Box<SomeTrait> { 
        println!("hello")
        box Bar as Box<SomeTrait>
    }
}

或者比印刷更具戏剧性的东西。)

这是一个由UFCS填充的语言空洞。目前,您需要使用虚拟 - Self技巧:

trait SomeTrait {
    fn new(_dummy: Option<Self>) -> Box<SomeTrait>;
    ...
}

然后被称为SomeTrait::new(None::<SomeStruct>)

但是,我怀疑为什么要从构造函数返回一个盒装对象。这通常不是一个好主意,通常直接返回普通类型会更好,并且用户可以在必要时将其打包,即

trait SomeTrait {
    fn new() -> Self;
    ...
}

(注意:此签名提及Self,因此上面的Option诀窍并非必需。)


旁注:错误信息相当糟糕,但它只反映了这些方法的实现方式; impl Foo中的关联函数与编写mod Foo { fn ... }非常相似。您可以通过强制编译器创建该模块来看到它的不同之处:

struct Foo;
impl Foo {
    fn bar() {}
}

fn main() {
    Foo::baz();
}

仅打印

<anon>:7:5: 7:13 error: unresolved name `Foo::baz`.
<anon>:7     Foo::baz();
             ^~~~~~~~

即。 Foo&#34;模块&#34;存在。