簡體   English   中英

為什么編譯器需要一個 trait 的實現來調用默認的自由函數?

[英]Why does the compiler need an implementation of a trait to call a default free function?

當對不帶self的特征調用默認實現時,為什么需要注釋實現類型?

下面是一個最小的、可重復的示例playground ):

mod builder {
    pub trait Builder: Sized {
        fn new() -> Simple {
            Simple
        }
    }

    pub struct Simple;

    impl Builder for Simple {}
}

pub fn main() {
    let _ = builder::Builder::new();
    
    /* Working version */
    // use builder::Builder;
    // let _ = builder::Simple::new();
}

這使:

error[E0283]: type annotations needed
  --> src/main.rs:14:13
   |
3  |         fn new() -> Simple {
   |         ------------------ required by `builder::Builder::new`
...
14 |     let _ = builder::Builder::new();
   |             ^^^^^^^^^^^^^^^^^^^^^ cannot infer type
   |
   = note: cannot satisfy `_: builder::Builder`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0283`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

E0283的編譯器解釋沒有提到默認實現,我同意這是有道理的。 但是對於默認實現,為什么需要類型?

這不僅是默認實現,而且是非常特殊的情況,其中該默認實現在其參數、結果和正文中甚至沒有提及Self / self

我發現更容易理解的規則是,在任何情況下,每次我們使用 trait 時都需要一個類型,而不是« 除非默認實現在其參數、結果和正文中甚至沒有提到Self / self »

對於這個非常具體的用例,您不想在調用所需函數時顯式命名類型,我建議使用免費函數。

mod builder {
    // ...
    pub fn make_default() -> Simple {
        Simple
    }
    // ...
}

pub fn main() {
    let _ = builder::make_default();
}

Rust 中提供的方法與 Java 中的static方法不同。 即使沒有參數和默認實現的函數也可以被實現者覆蓋。 考慮添加另一種實現Builder但覆蓋new函數的類型:

struct Noisy {}

impl builder::Builder for Noisy {
    fn new() -> builder::Simple {
        println!("Ahahahah I'm creating a Simple!!!11!");
        builder::Simple
    }
}

fn main() {
    // wait, should this call builder::Simple::new() or Noisy::new()?
    let _ = builder::Builder::new();
}

如果您想要始終具有相同行為的 Java static函數的效果,則應使用自由函數,正如prog-fh 的回答所建議的那樣。

暫無
暫無

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

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