【问题标题】:Implementing Rust traits cause struct to not be found实现 Rust 特征会导致找不到 struct
【发布时间】:2014-08-29 07:37:28
【问题描述】:

当我在 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 突然不见了?谢谢!

【问题讨论】:

    标签: struct rust traits


    【解决方案1】:

    目前,trait 中的关联函数(非方法函数)是通过 trait 调用的,即SomeTrait::new()。但是,如果您只是编写此代码,编译器将无法计算出您正在使用 which impl,因为无法指定 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 填补。目前,您需要使用 dummy-Self 技巧:

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

    然后被称为SomeTrait::new(None::&lt;SomeStruct&gt;)

    但是,我质疑您为什么要从构造函数返回一个装箱的对象。这很少是一个好主意,通常最好直接返回普通类型,如果需要,用户可以将其装箱,即

    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“模块”存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-15
      • 2016-05-29
      • 2021-08-20
      • 2022-12-07
      • 2020-12-24
      • 2023-03-29
      • 2022-08-15
      • 2020-05-09
      相关资源
      最近更新 更多