devstory

Méthodes dans Dart

  1. Qu'est-ce qu'une méthode ?
  2. La méthode régulière
  3. La méthode statique
  4. La méthode abstraite
  5. Les paramètres optionnels
  6. Les paramètres optionnels nommés
  7. Outrepasser une méthode
  8. Final method?

1. Qu'est-ce qu'une méthode ?

Dans le langage de programmation Dart, une méthode est un bloc de code défini dans une classe et exécuté uniquement lorsqu'il est appelé. Les méthodes divisent une grande tâche en petites parties et effectuent une opération de programme spécifique. Ce processus augmente la réutilisabilité du code et améliore l'approche modulaire du programme.
En règle générale, les méthodes sont divisées en 3 types:
  • La méthode régulière (non statique et non abstrait)
  • La méthode statique (static method).
  • La méthode abstraite (abstract method).

2. La méthode régulière

La syntaxe utilisée pour définir une méthode régulière :
return_type method_name(arguments)    {  
     // statement(s)  
}
  • return_type: Le type de données de retour de la méthode. Utiliser le mot-clef void comme type de retour si la méthode ne renvoie rien.
  • method_name: Le nom de la méthode. Contrairement à d'autres langages comme Java, Dart n'autorise pas deux méthodes ayant le même nom, même si elles ont des paramètres différents. Ceci est nécessaire pour pouvoir convertir le code Dart en JavaScript.
  • arguments: Les paramètres de la méthode.
Par exemple : La classe Cat et sa méthode sayHello(..). Pour convoquer sayHello(..), vous devez créer un objet Cat et convoquer la méthode en utilisant la notation par points (dot notation).
method_ex1.dart
class Cat {
  void sayHello(String name) {
    print("Hello $name");
  }
}
void main() {
  Cat tom = new Cat(); // Create a Cat object.  
  tom.sayHello("Jerry"); // Call the method through the object.
}
Output:
Hello Jerry
Une méthode peut contenir 0, 1 ou plusieurs paramètres, séparés par des virgules.
method_ex2.dart
class Rectangle {
  int width;
  int height;
  Rectangle(this.width, this.height); // Constructor

  int getArea() {
    return width * height;
  }
  void changeWidthHeight(int newWidth, int newHeight)  {
      width = newWidth;
      height = newHeight;
  }
  void showMe()  {
     print('I am a rectangle, width: $width, height: $height');
  }
}
void main() {
   Rectangle rec = Rectangle(5, 10); // Create an object.
   
   rec.showMe();  // Call the method.
   var area = rec.getArea();  // Call the method.
   print('Area: $area');
   print(' --- Change width and height --- ');
   rec.changeWidthHeight(25, 15); // Set newWidth, newHeight
   rec.showMe(); // Call the method.  
   area = rec.getArea(); // Call the method.
   print('Area: $area');
}
Output:
I am a rectangle, width: 5, height: 10
Area: 50
--- Change width and height ---
I am a rectangle, width: 25, height: 15
Area: 375

3. La méthode statique

Dart utilise le mot-clef static et la syntaxe de définition de méthode standard pour définir une méthode statique.
La syntaxe utilisée pour définir la méthode statique :
static return_type method_name(arguments)    {  
     // statement(s)  
}
Les caractéristiques de la méthode statique :
  • La méthode statique est convoquée à travers le nom de la classe et la notation par points. Par exemple MyUtility.sum(100, 50). Le nom de classe et la notation par points peuvent être omis si vous convoquez la méthode statique en interne.
  • Les membres non statiques d'une classe ne peuvent pas apparaître dans une méthode statique à moins qu'ils ne soient accessibles via l'objet (Voir l'exemple ci-dessous).
method_static_ex1.dart
class MyUtility {
  static int sum(int a, int b)  {
    return a + b;
  }
  static int minus(int a, int b)  {
    return a - b;
  }
}
void main() {
   var result = MyUtility.sum(100, 50);
   print('Sum Result: $result');
   result = MyUtility.minus(100, 50);
   print('Minus Result: $result');
}
Output:
Sum Result: 150
Minus Result: 50
Ensuite, observer l'exemple ci-dessous :
  • side1, side2 et side3 sont des champs (field) non statiques de la classe Triangle, qui ne peuvent pas apparaître dans la méthode statique.
  • La convocation d'une méthode statique dans la classe qui l'a définie peut ne pas avoir besoin du nom de la classe et de la notation par points (dot notation).
method_static_ex2.dart
class Triangle {
  late double side1;
  late double side2;
  late double side3;
  static const String DEFAULT_COLOR  = 'blue'; // Static field

  Triangle(double s1, double s2, double s3) {
    bool valid = isValidSides(s1, s2, s3); // Check if all sides are valid.
    if(!valid) {
      throw ArgumentError('Invalid Sides!'); // Throw an Error.
    }
     side1 = s1;
     side2 = s2;
     side3 = s3;
  }
  static bool isValidSides(double s1, double s2, double s3)  {
     if(s1 < 0 || s2 < 0 || s3 < 0)  {
       return false;
     }
     return s1 + s2 > s3 && s1 + s3 > s2 && s2 + s3 > s1;
  }
  bool isEquilateralTriangle() {
      return side1 == side2 && side2 == side3;
  }
}
void main() {
   bool valid = Triangle.isValidSides(6, 8, 10);
   print('Are sides 6, 8 and 10 valid to make a triangle? $valid');
   var triangle = Triangle(3.0, 4.0, 5.0);
   // Check if the triangle is equilateral triangle.
   var check = triangle.isEquilateralTriangle();
   print('Is Equilateral Triangle? $check');
}
Output:
Are sides 6, 8 and 10 valid to make a triangle? true
Is Equilateral Triangle? false

4. La méthode abstraite

Dans le langage Dart, la méthode abstraite est une méthode non statique et ne dispose pas de corps.
abstract return_type method_name(arguments);
Une classe avec au moins une méthode abstraite doit être déclarée abstraite. L'une de ses sous-classes remplacera les méthodes abstraites et écrira du contenu pour celles-ci.
Par exemple : La classe Person ci-dessous doit être déclarée comme classe abstraite car elle possède au moins une méthode abstraite.
method_abstract_ex1.dart
abstract class Person {
  void sayHello(); // An abstract method.
}
class EnglishPerson extends Person {
  void sayHello() {
    print("Hello");
  }
}
class RussianPerson extends Person {
   void sayHello() {
      print("Привет");
   }
}
void main() {
    Person enPerson = EnglishPerson();
    enPerson.sayHello();
    Person ruPerson = RussianPerson();
    ruPerson.sayHello();
}
Output:
Hello
Привет
  • Dart Classes

5. Les paramètres optionnels

Comme mentionné ci-dessus, les classes dans Dart et JavaScript ne prennent pas en charge les méthodes ayant le même nom, mais une méthode peut inclure des paramètres optionnels.
La syntaxe :
// Non-static method with optional arguments:
return_type method_name(typeM argM, typeN argN,[typeP? argP, typeQ? argQ]){  
     // statement(s)  
}
// Static method with optional arguments:
static return_type method_name(typeM argM, typeN argN,[typeP? argP, typeQ? argQ]){   
     // statement(s)  
}
// Abstract method with optional arguments:
return_type method_name(typeM argM, typeN argN,[typeP? argP, typeQ? argQ]);
Ou syntaxe - Paramètres optionnels avec des valeurs par défaut :
// Non-static method with optional arguments:
return_type method_name(typeM argM, typeN argN,
                        [typeP? argP = defaultValueP, typeQ? argQ]){  
     // statement(s)  
}
// Static method with optional arguments:
static return_type method_name(typeM argM, typeN argN,
                        [typeP? argP = defaultValueP, typeQ? argQ]){   
     // statement(s)  
}
// Abstract method with optional arguments:
return_type method_name(typeM argM, typeN argN,
                        [typeP? argP = defaultValueP, typeQ? argQ]);
Par exemple :
method_optional_args_ex1.dart
class MyUtility {
  static String concat(String s1, String s2, [String? s3]) {
    if (s3 != null) {
      return s1 + s2 + s3;
    }
    return s1 + s2;
  }
  static double sum(double v1, double v2, [double? v3, double? v4]) {
    return v1 + v2 + (v3 ?? 0) + (v4 ?? 0);
  }
}
void main() {
  String result1 = MyUtility.concat('One', 'Two');
  print('result1: $result1');
  String result2 = MyUtility.concat('One', 'Two', 'Three');
  print('result2: $result2');
  double value1 = MyUtility.sum(1, 2, 3, 4);
  print('value1: $value1');
  double value2 = MyUtility.sum(1, 2, 3);
  print('value2: $value2');
  double value3 = MyUtility.sum(1, 2);
  print('value3: $value3');
}
Output:
result1: OneTwo
result2: OneTwoThree
value1: 10.0
value2: 6.0
value3: 3.0
Par exemple :
method_optional_args_ex2.dart
class Team {
   List<String> members = [];

   void addMembers(String member1, [String? member2, String? member3]) {
      members.add(member1);
      if(member2!= null) {
         members.add(member2);
      }
      if(member3!= null) {
         members.add(member3);
      }
   }
   void printAllMembers()  {
      print(' --- All members: --- ');
      for(var member in members) {
          print(member);
      }
   }
}  
void main() {
  var team = Team(); // Create Team object.
  team.addMembers('Tom', 'Jerry');
  team.printAllMembers();
}
Output:
--- All members: ---
Tom
Jerry

6. Les paramètres optionnels nommés

Les paramètres nommés optionnels (Optional Named Parameters) sont des paramètres entre accolades { } et sont les derniers paramètres de la liste des paramètres. Tous ces paramètres ont des valeurs par défaut.
La syntaxe :
// Non-static method with optional named parameters:
return_type method_name(typeM argM, typeN argN,
                  {typeP paramP = defaultValueP, typeQ paramQ = defaultValueQ}){  
     // statement(s)  
}
// Static method with optional arguments:
static return_type method_name(typeM argM, typeN argN,
                  {typeP paramP = defaultValueP, typeQ paramQ = defaultValueQ}){  
     // statement(s)  
}
// Abstract method with optional arguments:
return_type method_name(typeM argM, typeN argN,
                  {typeP paramP = defaultValueP, typeQ paramQ = defaultValueQ});
Par exemple :
method_optional_named_args_ex1.dart
class StringUtility {
  static String concatAndTrim(String s1, String s2, {bool trimLeft = true, bool trimRight = true}) {
    var s = s1 + s2;
    if (trimLeft && trimRight) {
      return s.trim();
    } else if (trimLeft) {
      return s.trimLeft();
    } else if (trimRight) {
      return s.trimRight();
    }
    return s;
  }
}
void main() {
  var s1 = '  One  ';
  var s2 = '  Two  ';
  var result1 = StringUtility.concatAndTrim(s1, s2); // trim left and right
  print('result1: -->$result1<-- (Trim left and right)');

  var result2 = StringUtility.concatAndTrim(s1, s2, trimLeft: false); // trim right only
  print('result2: -->$result2<-- (Trim right only)');

  var result3 = StringUtility.concatAndTrim(s1, s2, trimRight: false); // trim left only
  print('result3: -->$result3<-- (Trim left only)' );

  var result4 = StringUtility.concatAndTrim(s1, s2, trimLeft: false, trimRight: false); // no trim
  print('result4: -->$result4<!-- (No Trim)');
}
Output:
result1: -->One    Two<-- (Trim left and right)
result2: -->  One    Two<-- (Trim right only)
result3: -->One    Two  <-- (Trim left only)
result4: -->  One    Two  <!-- (No Trim)

7. Outrepasser une méthode

Une sous-classe peut outrepasser (override) une méthode de la classe parente si les conditions suivantes sont réunies :
  • Les deux méthodes doivent avoir le même nom et les mêmes paramètres.
  • Le type de retour des deux méthodes doit être le même ou le type de retour de la méthode dans la sous-classe doit être un sous-type du type de retour de la méthode dans la classe parente.
Par exemple :
  • La classe Cat remplace la méthode sayAnything() de la classe Animal.
  • @override est une annotation facultative placée devant la méthode surchargée (dans la sous-classe). Si vous renommez accidentellement cette méthode dans la classe parent, le compilateur Dart vous donnera une erreur.
method_override_ex1.dart
class Animal {
  void sayAnything() {
    print('<Nothing>');
  }
}
class Cat extends Animal {
  @override
  void sayAnything() { // Override method from parent class.
    print('Meow');
  }
}
void main() {
  Animal animal = Cat();
  animal.sayAnything();
}
Output:
Meow
Par exemple : Utiliser le mot-clef super pour appeler une méthode de la classe parente.
method_override_ex2.dart
class BoldFormatter {
  String formatText(String text) {
    return '<b>' + text + '</b>';
  }
}
class BoldItalicFormatter extends BoldFormatter {
  @override
  String formatText(String text) { // Override method from parent class.
    var boldText = super.formatText(text); // Call super method.
    return '<i>' + boldText + '</i>';
  }
}
void main() {
  var formatter = BoldItalicFormatter();
  var formattedText = formatter.formatText('Hello');
  print(formattedText);
}
Output:
<i><b>Hello</b></i>

8. Final method?

Dans le langage Java, vous pouvez utiliser le mot-clef final d'une méthode pour vous assurer que les sous-classes ne peuvent pas surcharger cette méthode. Existe-t-il quelque chose de similaire dans Dart ?
package:meta vous donne @nonVirtual pour empêcher une sous-classe de remplacer une méthode de la classe parent. Cela aide Analyzer à signaler une erreur si vous commettez cette infraction, mais aucune autre action n'est entreprise.
method_final_ex1.dart
import 'package:meta/meta.dart';

class Foo {
   @nonVirtual
   void bar() {
     print("bar from Foo!");
   }
}
class SubFoo extends Foo {
  @override
   void bar()  {
      print("bar from SubFoo");
   }
}
En règle générale, vous recevrez un avertissement d'Analyzer qui ressemble à ceci :
The member 'bar' is declared non-virtual in 'Foo'
and can't be overridden in subclasses.dart(invalid_override_of_non_virtual_member)
  • Thêm thư viện vào dự án Dart