我试图理解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,所以我怎样才能使这个(或者正确的方法)工作,即。如果可能,请使用Stdin
或File
,甚至是String
(无法找到实施方案),以便在需要Read
时使用?< / p>
我不认为我可以在这里使用泛型,因为我需要将r
的实例(可能是实现Read
的任何内容)传递给其他方法,但请告诉我如果我错了。
答案 0 :(得分:2)
您可能希望在此处使用trait objects。您可以通过两种方式使用特征:
fn foo<T: Trait>(x: T)
。对于实现T
&#34; Trait
,其内容为&#34;
fn foo(x: &Trait)
。这提升了&#34;但固定&#34;通过使用特征对象来限制第一个版本。如果您想拥有一个可以保留对Stdin
或File
或其他任何实现Read
的引用的变量,那么您就不能使用静态调度解决方案,因为您的实施类型没有修复。
那么你的变量的类型是什么呢? Read
?可悲的是,它并不那么容易。特征对象是unsized,不能直接在堆栈上使用。相反,您只能通过引用/指针与特征对象进行交互,例如&Read
,&mut Read
,Box<Read>
等。现在我们使用借来的东西,我们可能会遇到更多与之相关的问题。幸运的是,您还没遇到第一个遇到此问题的人:请参阅this question详细了解此特定用例。
为简化一点,在大多数情况下可以使用Box<Trait>
。在你的情况下,它看起来像这样:
use std::io::{stdin, Read};
fn main() {
let r: Box<Read> = Box::new(stdin());
println!("ok");
}