[英]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.