Il est très utile pour de lire complètement le trait que vous implémentez pour voir comment l'implémenter. Le Fn
trait est défini comme:
pub trait Fn<Args>: FnMut<Args> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
Avis des différences entre la mise en œuvre et la définition? Je vois beaucoup:
La mise en œuvre ne fournit pas de valeur pour Args
! C'est ce que le compilateur pointe vers. Voir aussi Wrong number of type arguments: expected 1 but found 0
La mise en œuvre n'implémente pas le supertrait FnMut
, ce qui nécessite lui-même le supertrait FnOnce
. FnOnce
est où le associé typeOutput
est déclaré.
La mise en œuvre néglige de définir quel type de béton Output
devrait être. L'implémentation renvoie Self
alors que l'attribut renvoie Self::Output
.
L'implémentation n'accepte pas le second argument à call
. Cet argument contient des arguments transmis.
De plus, les types à utiliser Rust PascalCase
, pas snake_case
, il devrait donc être Foo
.
#![feature(unboxed_closures)]
#![feature(fn_traits)]
struct Foo;
impl Fn<()> for Foo {
extern "rust-call" fn call(&self, _args:()) {
println!("Call (Fn) for Foo");
}
}
impl FnMut<()> for Foo {
extern "rust-call" fn call_mut(&mut self, _args:()) {
println!("Call (FnMut) for Foo");
}
}
impl FnOnce<()> for Foo {
type Output =();
extern "rust-call" fn call_once(self, _args:()) {
println!("Call (FnOnce) for Foo");
}
}
fn main() {
let x = Foo;
x();
}
Normalement cependant, la mise en œuvre qu'un seul trait aurait un code intéressant et les autres implémentations de trait pourrait déléguer:
extern "rust-call" fn call(&self, args:()) {
println!("Foo called, took args: {:?}", args);
}
// ...
extern "rust-call" fn call_mut(&mut self, args:()) {
self.call(args)
}
// ...
extern "rust-call" fn call_once(self, args:()) {
self.call(args)
}
Merci beaucoup! Très bonne explication. –
@ АндрейЛедовских vous êtes les bienvenus. Rappelez-vous d'augmenter les réponses utiles et d'accepter la réponse qui vous a le plus aidé à résoudre votre problème. – Shepmaster