devstory

Méthodes dans TypeScript

  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 avec les valeurs par défaut
  7. Les paramètres avec le type de données union
  8. Outrepasser une méthode
  9. Method Overloading

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

Dans le langage de programmation TypeScript, une méthode est un bloc de code, défini à l'intérieur d'une classe et exécute uniquement lorsqu'il est convoqué. Les méthodes divisent une grande tâche en petites parties et effectuent l'opération spécifique de ce programme. Ce processus augmente la réutilisabilité du code et améliore l'approche modulaire du programme.
A la base, 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 pour définir une méthode régulière :
[private | protected | public] method_name(arguments) : return_type {  
     // 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. A l'inverse des autres langages comme Java, TypeScript n'accepte pas deux méthodes ayant le même nom, même si elles disposent des paramètres différents. Ceci est nécessaire pour pouvoir convertir le code TypeScript en Javascript.
  • arguments: Les paramètres de la méthode.
Par exemple : La classe Cat et sa méthode sayHello(..). Afin de convoquer la méthode sayHello(..), il convient de créer un objet Cat et convoquer la méthode en utilisant la notation par points (dot notation).
method_ex1.ts
class Cat {
    sayHello(name: string): void {
        console.log(`Hello ${name}`);
    }
}
function method_ex1_test() {
    var tom: Cat = new Cat(); // Create a Cat object.
    tom.sayHello("Jerry"); // Call the method through the object.
}
// Call the method:
method_ex1_test();
Output:
Hello Jerry
Une méthode peut contenir 0, 1, ou plus de paramètres, séparés par des virgules.
method_ex2.ts
class Rectangle {
    width: number;
    height: number;

    constructor(width: number, height: number) {
        this.width = width;
        this.height = height;
    }
    getArea(): number {
        return this.width * this.height;
    }
    changeWidthHeight(newWidth: number, newHeight: number): void {
        this.width = newWidth;
        this.height = newHeight;
    }
    showMe(): void {
        console.log(`I am a rectangle, width: ${this.width}, height: ${this.height}`);
    }
}
function method_ex2_test() {
    var rec = new Rectangle(5, 10); // Create an object.

    rec.showMe();  // Call the method.
    var area = rec.getArea();  // Call the method.
    console.log(`Area: ${area}`);

    console.log(` --- Change width and height --- `);
    rec.changeWidthHeight(25, 15); // Set newWidth, newHeight

    rec.showMe(); // Call the method.  
    area = rec.getArea(); // Call the method.
    console.log(`Area: ${area}`);
}
method_ex2_test(); // Call the function.
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

TypeScript utilise le mot-clef static en conjonction avec la syntaxe de définition de méthode standard pour définir une méthode statique.
La syntaxe :
[private | protected | public] static method_name(arguments) : return_type {  
     // statement(s)  
}
Les caractéristiques des méthodes statiques :
  • La méthode statique est convoquée à travers le nom de classe et la notation par points. Par exemple MyUtility.sum(100, 50).
  • Les membres non statiques d'une classe ne peuvent pas apparaître dans une méthode statique à moins qu'ils ne soient accessibles à travers l'objet (voir l'exemple ci-dessous).
method_static_ex1.ts
class MyUtility {
    static sum(a: number, b: number): number { // same as 'public'
        return a + b;
    }
    public static minus(a: number, b: number): number {
        return a - b;
    }
}
function method_static_ex1_test() {
    var result = MyUtility.sum(100, 50);
    console.log(`Sum Result: ${result}`);

    result = MyUtility.minus(100, 50);
    console.log(`Minus Result: ${result}`);
}
method_static_ex1_test(); // Call the method
Output:
Sum Result: 150
Minus Result: 50
Ensuite, observer l'exemple ci-dessous :
  • side1, side2 et side3 sont les champs non-statiques de la classe Triangle, ils ne peuvent pas apparaître dans la méthode statique.
method_static_ex2.ts
class Triangle {
    side1: number; side2: number; side3: number;// Non-static fields (Cann't use in static method)
    static DEFAULT_COLOR:string = 'blue'; // Static field (Can use in static method)

    constructor(s1: number, s2: number, s3: number) {
        var valid = Triangle.isValidSides(s1, s2, s3); // Check if all sides are valid.
        if (!valid) {
            throw new Error('Invalid Sides!'); // Throw an Error.
        }
        this.side1 = s1;
        this.side2 = s2;
        this.side3 = s3;
    }
    static isValidSides(s1: number, s2: number, s3: number): boolean {
        if (s1 < 0 || s2 < 0 || s3 < 0) {
            return false;
        }
        return s1 + s2 > s3 && s1 + s3 > s2 && s2 + s3 > s1;
    }
    isEquilateralTriangle(): boolean {
        return this.side1 == this.side2 && this.side2 == this.side3;
    }
}
function method_static_ex2_test() {
    var valid = Triangle.isValidSides(6, 8, 10);
    console.log(`Are sides 6, 8 and 10 valid to make a triangle? ${valid}`);

    var triangle = new Triangle(3.0, 4.0, 5.0);
    // Check if the triangle is equilateral triangle.
    var check = triangle.isEquilateralTriangle();
    console.log(`Is Equilateral Triangle? ${check}`);
}
method_static_ex2_test(); // Call the method.
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 TypeScript, une méthode abstraite est une méthode non statique et n'a pas de contenu.
[protected | public] abstract method_name(arguments) : return_type;
Une classe avec au moins une méthode abstraite doit être déclarée abstraite, et l'une de ses sous-classes doit outrepasser ces méthodes abstraites et écrire du contenu pour elles.
method_abstract_ex1.ts
abstract class Person {
    abstract sayHello(): void; // An abstract method.
}
class EnglishPerson extends Person {
    sayHello(): void {
        console.log("Hello");
    }
}
class RussianPerson extends Person {
    sayHello(): void {
        console.log("Привет");
    }
}
function method_abstract_ex1_test() {
    var enPerson = new EnglishPerson();
    enPerson.sayHello();

    var ruPerson = new RussianPerson();
    ruPerson.sayHello();
}
method_abstract_ex1_test(); // Call the function.
Output:
Hello
Привет
  • TypeScript Classes

5. Les paramètres optionnels

Comme mentionné ci-dessus, les classes dansTypeScript et JavaScript n'autorisent pas les méthodes portant le même nom, mais une méthode peut inclure des paramètres optionnels.
La syntaxe :
// Non-static method with optional arguments:
[private | protected | public] method_name(args, optional_args?): return_type {  
     // statement(s)  
}

// Static method with optional arguments:
[private | protected | public] static method_name(args, optional_args?) : return_type {  
     // statement(s)  
}

// Abstract method with optional arguments:
[protected | public] abstract method_name(args, optional_args?): return_type;
Par exemple :
method_optional_args_ex1.js
class MyUtils {
    static concat(s1: string, s2: string, s3?: string): string {
        if (s3) {
            return s1 + s2 + s3;
        }
        return s1 + s2;
    }
    static sum(v1: number, v2: number, v3?: number, v4?: number): number {
        return v1 + v2 + (v3 ?? 0) + (v4 ?? 0);
    }
}
function method_optional_args_ex1_test() {
    var result1 = MyUtils.concat('One', 'Two');
    console.log(`result1: ${result1}`);

    var result2 = MyUtils.concat('One', 'Two', 'Three');
    console.log(`result2: ${result2}`);

    var value1 = MyUtils.sum(1, 2, 3, 4);
    console.log(`value1: ${value1}`);

    var value2 = MyUtils.sum(1, 2, 3);
    console.log(`value2: ${value2}`);

    var value3 = MyUtils.sum(1, 2);
    console.log(`value3: ${value3}`);
}
method_optional_args_ex1_test(); // Call the method.
Output:
result1: OneTwo
result2: OneTwoThree
value1: 10
value2: 6
value3: 3

6. Les paramètres avec les valeurs par défaut

TypeScript prend en charge les méthodes avec des paramètres par défaut, qui doivent être les derniers de la liste des paramètres.
La syntaxe :
// Non-static method
[private | protected | public ] method_name (
             arg1 : data_type1, arg2 : data_type2,
             arg3 : data_type3 = defaultValue3,
             arg4 : data_type4 = defaultValue4) : return_type {
    // statement(s)  
}
// Static method
[private | protected | public ] static method_name (
             arg1 : data_type1, arg2 : data_type2,
             arg3 : data_type3 = defaultValue3,
             arg4 : data_type4 = defaultValue4) : return_type {
   // statement(s)  
}
// Abstract method
[protected | public ] abstract method_name (
             arg1 : data_type1, arg2 : data_type2,
             arg3 : data_type3 = defaultValue3,
             arg4 : data_type4 = defaultValue4) : return_type;
Par exemple :
method_default_value_args_ex1.ts
class SalesUtils {
    static applyDiscount(amount : number, discount: number = 0.05)  : number {
        return amount * (1 - discount);
    }
}
function method_default_value_args_ex1_test() {
    var value1 = SalesUtils.applyDiscount(1000);
    console.log(`value1 = ${value1}`);

    var value2 = SalesUtils.applyDiscount(1000, 0.5);
    console.log(`value2 = ${value2}`);
}
method_default_value_args_ex1_test(); // Call the method.
Output:
value1 = 950
value2 = 500

7. Les paramètres avec le type de données union

Le paramètre d'une méthode peut également être déclaré avec un type de données union (union data type).
// Non-static method
[private | protected | public ] method_name (
             arg1 : data_type1, arg2 : data_type2,
             arg3 : data_type31 | data_type32 | data_type3N, // Union Data Type
             arg4 : data_type4 = defaultValue4) : return_type {
    //  Statament(s)
}
// Static method
[private | protected | public ] static method_name (
             arg1 : data_type1, arg2 : data_type2,
             arg3 : data_type31 | data_type32 | data_type3N, // Union Data Type
             arg4 : data_type4) : return_type {
    //  Statament(s)  
}
// Abstract method
[protected | public ] abstract method_name (
             arg1 : data_type1, arg2 : data_type2,
             arg3 : data_type31 | data_type32 | data_type3N, // Union Data Type
             arg4 : data_type4) : return_type;
Par exemple :
method_union_type_args_ex1.ts
interface IStudent {
    studentId: number,
    studentName: string
}
interface IWorker {
    workerId: number,
    workerName: string
}
class AppUtils {
    static getName(person: IStudent | IWorker): string { // Union Type Arg
        var p = person as IStudent;
        if (p.studentName) {
            return p.studentName;
        }
        return (person as IWorker).workerName;
    }
}
function method_union_type_args_ex1_test() {
    var student = { studentId: 1, studentName: "Tom" };
    var worker = { workerId: 2, workerName: "Jerry" };

    var name1 = AppUtils.getName(student);
    var name2 = AppUtils.getName(worker);
    console.log(`name1: ${name1}`);
    console.log(`name2: ${name2}`);
}
method_union_type_args_ex1_test(); // Call the method.
Output:
name1: Tom
name2: Jerry

8. 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 renvoie des deux méthodes doit être le même, ou le type de renvoie de la méthode dans la sous-classe doit être un sous-type du type de renvoie de la méthode dans la classe parent.
Par exemple :
  • La classe Mouse outrepasse (override) la méthode sayAnything() de la classe Animal.
method_override_ex1.ts
class Animal {
    sayAnything(): void {
        console.log('<Nothing>');
    }
}
class Mouse extends Animal {
    sayAnything(): void { // Override method of parent class.
        console.log('Hi Tom!');
    }
}
function method_override_ex1_test() {
    var animal = new Mouse();
    animal.sayAnything(); // Hi Tom!
}
method_override_ex1_test(); // Call the function.
Output:
Hi Tom!
Par exemple : Vous pouvez également utiliser le mot-clef super pour convoquer une méthode ayant le même nom que la classe parente.
method_override_ex2.ts
class BoldFormatter {
    formatText(text: string): string {
        return '<b>' + text + '</b>';
    }
}
class BoldItalicFormatter extends BoldFormatter {
    formatText(text: string): string { // Override method of parent class.
        var boldText = super.formatText(text); // Call super method.
        return '<i>' + boldText + '</i>';
    }
}
function method_override_ex2_test() {
    var formatter = new BoldItalicFormatter();
    var formattedText = formatter.formatText('Hello');
    console.log(formattedText);
}
method_override_ex2_test(); // Call the method.
Output:
<i><b>Hello</b></i>

9. Method Overloading

Dans un article sur les fonctions dans TypeScript, j'ai introduit "Function Overloading". La méthode est considérée comme une fonction de la classe, elle a donc également un concept similaire, qui est "Method Overloading" (la surcharge de méthode).
TypeScript n'accepte pas deux méthodes ayant le même nom dans une classe même si elles ont des paramètres différents. La Method Overloading vous permet de définir une méthode avec différents types de paramètres.
Dans TypeScript, la surcharge de méthode est différente de C++, Java ou C#. L'idée principale de la surcharge de méthode est de créer une méthode générique qui vérifie le type de paramètre qui a été transmis lorsque la méthode a été convoquée, ensuite, de faire une logique pour le cas approprié. Il est utile d'ajouter des définitions à la méthode pour aider les autres programmeurs à savoir comment l'utiliser de manière appropriée.
La syntaxe :
// Definition 1
[static] method_name(arg_11 : type_11, arg_1N : type_1N): return_type;
]// Definition 2
[static] method_name(arg_21 : type_21, arg_22 : type_22, arg_2M : type_2M) : return_type;
[static] method_name(... args : any[]) : return_type {
   // Method body.
}
Par exemple :
method_overloading_ex1.ts
interface IDimension {
    width: number,
    height: number
}
class MathUtils {
    static getArea(dimension: IDimension): number; // Definition 1
    static getArea(width: number): number; // Definition 2
    static getArea(width: number, height: number): number; // Definition 3
    static getArea(...args: any[]): number {
        if (args.length == 1) {
            if (typeof args[0] == 'number') { // Use Definition 2
                return args[0] * args[0];
            } else { // Use Definition 1
                var dim = args[0] as IDimension;
                return dim.width * dim.height;
            }
        } else if (args.length == 2) {
            return args[0] * args[1];
        } else {
            throw new Error('Arguments Invalid!');
        }
    }
}
function method_overloading_ex1_test() {
    var area1 = MathUtils.getArea({ width: 10, height: 20 }); // 200
    var area2 = MathUtils.getArea(10); // 100
    var area3 = MathUtils.getArea(10, 15); // 150

    console.log(`area1: ${area1}`);
    console.log(`area2: ${area2}`);
    console.log(`area3: ${area3}`);
}
method_overloading_ex1_test(); // Call the function.
Output:
area1: 200
area2: 100
area3: 150