2 votes

Comment créer un setter avec un trait comme paramètre ?

Je viens de commencer avec Rust. J'aimerais créer un setter qui acceptera un trait comme paramètre. Pour illustrer l'idée

pub trait Engine {
  fn start() -> bool;
}

struct Car {
  engine: Box<dyn Engine>,
}

impl Car {
  pub fn new() -> Self {
    let engine = Box::new(DummyEngine {});
    Self {
      engine,
    }
  }
  pub fn set_engine(&mut self, engine: &dyn Engine) {
      self.engine = Box::new(engine);
  }
}

Le code setter se plaint :

the trait bound `&dyn Engine: Engine` is not satisfied
required for the cast to the object type `dyn Engine` rustcE0277

Par ailleurs, comment éviter l'utilisation d'un moteur par défaut factice ? Disons qu'une voiture n'a pas besoin de moteur. Doit-elle être enveloppée dans un Option ?

2voto

El Profesor Points 10915

Compte tenu de ce qui suit Engine qui spécifie start() en tant que méthode au lieu d'une fonction associée :

pub trait Engine {
  fn start(&mut self) -> bool;
}

Votre DummyEngine n'a pas l'air de mettre en œuvre le Engine trait. Vous pourriez simplement mettre en œuvre Engine para DummyEngine :

struct DummyEngine;

impl Engine for DummyEngine {
  fn start(&mut self) -> bool { false }
}

Cette approche - c'est-à-dire l'utilisation d'un objet factice - correspondrait à l'approche de la Modèle d'objet nul . Toutefois, vous pouvez opter pour Option à la place, comme vous l'avez suggéré, et définir Car comme :

struct Car {
  engine: Option<Box<dyn Engine>>,
}

De cette façon, vous pouvez mettre en œuvre new() y set_engine() comme :

impl Car {
  pub fn new() -> Self {
    Car {
      engine: None,
    }
  }

  pub fn set_engine(&mut self, engine: Box<dyn Engine>) {
    self.engine = Some(engine);
  }
}

Vous passerez un Box<dyn Engine> a set_engine() par valeur. Les Box possède le Engine et il sera déplacé dans le engine champ. En d'autres termes, le Box est déplacé dans le paramètre engine qui est à son tour déplacé dans la base de données de l engine champ de Car .


En tant que Car::new() ne prend pas d'arguments, vous pouvez vouloir implémenter la méthode Default trait pour Car également :

impl Default for Car {
   fn default() -> Self {
      Car::new()
   }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X