[英]A struct with a trait field, but optional
假設我有一個結構,其實現寫入某處,即實現std::io::Write
特征的東西。 但是,我不希望結構擁有它。 以下代碼有效:
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()
}
}
但是,現在這個書寫功能應該是可選的。 我認為這聽起來很容易,但現在以下內容無法編譯:
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()
}
}
}
因為:
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()`
我不確定如何解釋。
我嘗試通過將相關行更改為:
writeln!(self.out.as_ref().unwrap(), "The number is {}", i).unwrap()
但后來我得到
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
我真的不知道如何解釋這些錯誤消息,令人驚訝的是,在沒有真正理解的情況下,僅僅在隨機的地方撒上&
s 和mut
s,我並沒有真正到達任何地方!
(順便說一句,我不確定這是否是解決這個問題的“好”方法?我對解決這個問題的完全不同的方法持開放態度,這基本上是可選地將要寫入的內容傳遞到結構中,但沒有擁有它的結構。我讀到了可能也相關的Box
類型?)
如您所知,基於您已經將&mut
用於out
。 使用as_ref()
的問題是它返回一個不可變的引用。 相反,您需要使用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()
}
}
或者,您也可以簡化它並使用if let
更慣用地表達它:
pub fn print_number(&mut self, i: isize) {
if let Some(out) = &mut self.out {
writeln!(out, "The number is {}", i).unwrap()
}
}
我還建議不要展開,而是返回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(())
}
您還可以簡化您的路徑,例如std::io::Write
和std::io::Result<()>
,通過使用使用聲明導入它們,例如use std::io::{self, Write};
然后將它們更改為Write
和io::Result<()>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.