簡體   English   中英

具有特征字段的結構,但可選

[英]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::Writestd::io::Result<()> ,通過使用使用聲明導入它們,例如use std::io::{self, Write}; 然后將它們更改為Writeio::Result<()>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM