ProgrammationDéveloppeur Rust Backend

Comment sont organisées les méthodes et les fonctions associées en Rust ? En quoi diffèrent-elles les unes des autres, comment les déclarer et les appeler, et quand utiliser quelle option ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question

Rust emprunte le concept de méthodes aux langages orientés objet, mais les implémente différemment : au lieu du traditionnel this ou self, les méthodes prennent explicitement un paramètre self. Les fonctions associées, quant à elles, sont apparues comme une alternative aux méthodes statiques dans d'autres langages de programmation — elles sont liées au type, mais pas à une valeur spécifique.

Problème

On confond souvent méthodes, fonctions associées et fonctions libres. Il n'est pas toujours évident de savoir quand utiliser une méthode avec self et quand utiliser une fonction associée sans self. Il y a des questions de visibilité, d'auto-déréférencement et de transfert de propriété.

Solution

Les méthodes en Rust sont déclarées avec le premier paramètre self / &self / &mut self à l'intérieur d'un bloc impl (généralement pour struct ou enum). Elles sont appelées sur une instance : object.method(). Les fonctions associées (par exemple, new, from) sont également déclarées à l'intérieur d'un impl, mais sans le premier paramètre self et sont appelées avec des doubles deux-points : Type::function().

Exemple de code :

struct Point { x: f64, y: f64, } impl Point { // Fonction associée (constructeur) fn new(x: f64, y: f64) -> Self { Self { x, y } } // Méthode : nécessite self fn distance_from_origin(&self) -> f64 { (self.x.powi(2) + self.y.powi(2)).sqrt() } } let p = Point::new(3.0, 4.0); printf!("{}", p.distance_from_origin()); // 5.0

Caractéristiques clés :

  • Les méthodes prennent un paramètre self sous différentes variantes de propriété
  • Les fonctions associées ne prennent pas self, utilisées généralement pour l'initialisation ou les utilitaires
  • Seules les méthodes peuvent être appelées sur une instance via la notation par point, les fonctions associées — uniquement avec ::

Questions trompeuses.

Peut-on appeler des fonctions associées via une instance (avec un point) ?

C'est possible (par exemple, p.new(1.0, 2.0)), mais c'est fortement déconseillé : cela crée une confusion, car la fonction associée n'a pas accès à l'objet courant et l'instance est transmise sans être prise en compte. Il vaut mieux utiliser la syntaxe Type::func().

Exemple de code :

let p = Point::new(1.0, 2.0); let q = p.new(0.0, 0.0); // Ça marche, mais ce n'est pas une bonne pratique !

Les méthodes peuvent-elles être asynchrones ?

Oui. Les méthodes peuvent être déclarées avec le mot clé async tout comme les fonctions libres :

impl Foo { async fn do_async(&self) { // ... } }

Peut-on déclarer à l'intérieur d'un même bloc impl des méthodes et des fonctions associées ?

Oui — toutes les combinaisons sont possibles. Il est également possible de déclarer plusieurs blocs impl pour un même type.

Erreurs typiques et anti-patterns

  • Confondre méthodes et fonctions associées
  • Laisser des fonctions associées sans spécification d'appartenance au type (ne pas les déclarer dans impl)
  • Appeler des fonctions associées via une instance (avec un point)

Exemple de la vie réelle

Cas négatif

Un débutant a déclaré une fonction new en dehors de l'impl et a essayé de l'utiliser comme constructeur, puis a accidentellement appelée via une instance : p.new(1.0, 2.0).

Avantages :

Fonctionne rapidement (le compilateur le permet).

Inconvénients :

Code peu lisible, difficile à maintenir, compliqué d'utiliser des méthodes avec un bon transfert de propriété pour self.

Cas positif

Toutes les méthodes et fonctions associées sont déclarées strictement à l'intérieur de l'impl, et les bonnes syntaxes d'appel sont utilisées (Type::new() pour les constructeurs, obj.method() pour les actions).

Avantages :

Haute lisibilité, conformité aux meilleures pratiques.

Inconvénients :

Nécessite la connaissance des idiomes Rust et de l'attention au syntaxe.