[英]A struct with a trait field, but optional
Say I have a struct whose implementation writes somewhere , ie to something that implements the std::io::Write
trait.假设我有一个结构,其实现写入某处,即实现std::io::Write
特征的东西。 However, I don't want the struct to own this.但是,我不希望结构拥有它。 The following code works:以下代码有效:
fn main() {
let mut out = std::io::stdout();
let mut foo = Foo::new(&mut out);
foo.print_number(2);
}
struct Foo<'a> {
out: &'a mut dyn std::io::Write
}
impl<'a> Foo<'a> {
pub fn new(out: &'a mut dyn std::io::Write) -> Self {
Self {
out
}
}
pub fn print_number(&mut self, i: isize) {
writeln!(self.out, "The number is {}", i).unwrap()
}
}
But, now this writing functionality should be made optional.但是,现在这个书写功能应该是可选的。 I thought this sounds easy enough, but now the following doesn't compile:我认为这听起来很容易,但现在以下内容无法编译:
fn main() {
let mut out = std::io::stdout();
let mut foo = Foo::new(Some(&mut out));
foo.print_number(2);
}
struct Foo<'a> {
out: Option<&'a mut dyn std::io::Write>
}
impl<'a> Foo<'a> {
pub fn new(out: Option<&'a mut dyn std::io::Write>) -> Self {
Self {
out
}
}
pub fn print_number(&mut self, i: isize) {
if self.out.is_some() {
writeln!(self.out.unwrap(), "The number is {}", i).unwrap()
}
}
}
because of:因为:
error[E0507]: cannot move out of `self.out` which is behind a mutable reference
--> src/main.rs:20:26
|
20 | writeln!(self.out.unwrap(), "The number is {}", i).unwrap()
| ^^^^^^^^
| |
| move occurs because `self.out` has type `Option<&mut dyn std::io::Write>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `self.out.as_ref()`
which I'm not sure how to interpret.我不确定如何解释。
I tried following the suggestion by changing the line in question to:我尝试通过将相关行更改为:
writeln!(self.out.as_ref().unwrap(), "The number is {}", i).unwrap()
but then I get但后来我得到
error[E0596]: cannot borrow data in a `&` reference as mutable
--> src/main.rs:20:26
|
20 | writeln!(self.out.as_ref().unwrap(), "The number is {}", i).unwrap()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
I'm really not sure how to interpret these error messages and surprisingly I'm not really getting anywhere by just sprinkling &
s and mut
s in random places without really understanding!我真的不知道如何解释这些错误消息,令人惊讶的是,在没有真正理解的情况下,仅仅在随机的地方撒上&
s 和mut
s,我并没有真正到达任何地方!
(As an aside, I'm not sure if this is a "good" way of going about this anyway? I'm open to completely different approaches of solving this problem, which is basically to optionally pass something to write to into a struct, but without the struct owning it. I read about the Box
type which might also be relevant?) (顺便说一句,我不确定这是否是解决这个问题的“好”方法?我对解决这个问题的完全不同的方法持开放态度,这基本上是可选地将要写入的内容传递到结构中,但没有拥有它的结构。我读到了可能也相关的Box
类型?)
As you already know, based on you already using &mut
for out
.如您所知,基于您已经将&mut
用于out
。 The issue with using as_ref()
is that it returns an immutable reference.使用as_ref()
的问题是它返回一个不可变的引用。 Instead you need to use as_mut()
.相反,您需要使用as_mut()
。
pub fn print_number(&mut self, i: isize) {
if self.out.is_some() {
writeln!(self.out.as_mut().unwrap(), "The number is {}", i).unwrap()
}
}
Alternatively, you can also simplify this and express it more idiomatically using if let
:或者,您也可以简化它并使用if let
更惯用地表达它:
pub fn print_number(&mut self, i: isize) {
if let Some(out) = &mut self.out {
writeln!(out, "The number is {}", i).unwrap()
}
}
I would also suggest that instead of unwrapping, that you return the io::Result
and let the caller handle any potential error.我还建议不要展开,而是返回io::Result
并让调用者处理任何潜在的错误。
pub fn print_number(&mut self, i: isize) -> std::io::Result<()> {
if let Some(out) = &mut self.out {
writeln!(out, "The number is {}", i)?;
}
Ok(())
}
You can also simplify your paths, eg std::io::Write
and std::io::Result<()>
, by importing them with ause declaration , eg use std::io::{self, Write};
您还可以简化您的路径,例如std::io::Write
和std::io::Result<()>
,通过使用使用声明导入它们,例如use std::io::{self, Write};
and then changing them to Write
and io::Result<()>
.然后将它们更改为Write
和io::Result<()>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.