为什么不能将结构分配给具有其实现的特征的绑定

时间:2017-05-01 19:45:15

标签: rust

我试图理解Rust多态性。根据我在OOP中的背景,我希望以下Rust代码可以工作:

use std::io::{stdin, Read};

fn main() {
    let r: Read = stdin();
    println!("ok");
}

但它没有:

4 |     let r: Read = stdin();
  |                   ^^^^^^^ expected trait std::io::Read, found struct `std::io::Stdin`

我知道StdIn有一个Read impl,所以我怎样才能使这个(或者正确的方法)工作,即。如果可能,请使用StdinFile,甚至是String(无法找到实施方案),以便在需要Read时使用?< / p>

我不认为我可以在这里使用泛型,因为我需要将r的实例(可能是实现Read的任何内容)传递给其他方法,但请告诉我如果我错了。

1 个答案:

答案 0 :(得分:2)

您可能希望在此处使用trait objects。您可以通过两种方式使用特征:

  • 静态调度方式:fn foo<T: Trait>(x: T)。对于实现T&#34;
  • 的任意但已修复 Trait,其内容为&#34;
  • 动态调度方式:fn foo(x: &Trait)。这提升了&#34;但固定&#34;通过使用特征对象来限制第一个版本。

如果您想拥有一个可以保留对StdinFile或其他任何实现Read的引用的变量,那么您就不能使用静态调度解决方案,因为您的实施类型没有修复。

那么你的变量的类型是什么呢? Read?可悲的是,它并不那么容易。特征对象是unsized,不能直接在堆栈上使用。相反,您只能通过引用/指针与特征对象进行交互,例如&Read&mut ReadBox<Read>等。现在我们使用借来的东西,我们可能会遇到更多与之相关的问题。幸运的是,您还没遇到第一个遇到此问题的人:请参阅this question详细了解此特定用例。

为简化一点,在大多数情况下可以使用Box<Trait>。在你的情况下,它看起来像这样:

use std::io::{stdin, Read};

fn main() {
    let r: Box<Read> = Box::new(stdin());
    println!("ok");
}