Module
TypeScript
Module
Introduit dans ES6
Un fichier pouvant contenir des variables ; fonctions, classes, interfaces...
Propriet´
es´
Il est possible d’utiliser des e´le´ments de´finis dans un autre fichier : une variable,
une fonction, une classe, une interface...
Pour cela, il faut l’importer la`ou` on a besoin de l’utiliser
Pour importer un e´le´ment, il faut l’exporter dans le fichier source
En transpilant le fichier contenant les import, les fichiers contenant les
e´le´ments importe´s seront aussi transpile´s.
Module
TypeScript
E´tant donne´ le fichier [Link] dont le contenu est
function somme(a: number = 0, b: number = 0) {
return a + b;
}
function produit(a: number = 0, b: number = 1) {
return a * b;
}
Module export
TypeScript
Pour exporter les deux fonctions somme et produit de [Link]
export function somme(a: number = 0, b: number = 0) {
return a + b;
}
export function produit(a: number = 0, b: number = 1) {
return a * b;
}
Ou aussi
function somme(a:number = 0, b:number = 0) {
return a + b;
}
function produit(a: number = 0, b: number = 1) {
return a * b;
}
export { somme, produit };
Module import
TypeScript
Pour importer et utiliser une fonction
import { somme } from './fonctions';
[Link](somme(2, 5));
// affiche 7
Pour importer plusieurs e´le´ments
import { somme, produit } from './fonctions';
[Link](somme(2, 5));
// affiche 7
[Link](produit(2, 5));
// affiche 10
Module as
TypeScript
On peut aussi utiliser des alias
import { somme as s, produit as p } from './fonctions';
[Link](s(2, 5));
// affiche 7
[Link](p(2, 5));
// affiche 10
Ou aussi
import * as f from './fonctions';
[Link]([Link](2, 5));
// affiche 7
[Link]([Link](2, 5));
// affiche 10
Module as
TypeScript
Les alias peuvent eˆtre attribue´s a` l’exportation
function somme(a:number = 0, b:number = 0) {
return a + b;
}
function produit(a: number = 0, b: number = 1) {
return a * b;
}
export { produit as p, somme as s } ;
Pour importer
import * as f from './fonctions';
[Link](f.s(2, 5));
// affiche 7
[Link](f.p(2, 5));
// affiche 10
Module default
TypeScript
On peut aussi utiliser le export default (un seul par fichier)
export default function somme(a: number = 0, b: number = 0) {
return a + b;
}
export function produit(a: number = 0, b: number = 1) {
return a * b;
}
Pour importer, pas besoin de { } pour les e´le´ments exporter par de´faut
import somme from './fonctions';
import { produit } from './fonctions';
[Link](somme(2, 5));
// affiche 7
[Link](produit(2, 5));
// affiche 10
Classe Syntaxe
TypeScript
Conside´rons la classe Personne de´finie dans [Link]
export class Personne {
num : number;
nom : string;
prenom : string;
}
En TypeScript
Toute classe a un constructeur par de´faut sans parame`tre.
Par de´faut, la visibilite´ est public.
Classe Syntaxe
TypeScript
Hypothe`se
Si on voulait cre´er un objet de la classe Personne avec les valeurs 1, wick et john
E´tape 1 : Commenc¸ons par importer la classe Personne dans [Link]
import { Personne } from './personne';
E´tape 2 : de´clarons un objet (objet non cre´e´)
let personne: Personne;
E´tape 3 : cre´ons l’objet (instanciation) de type Personne (objet cre´e´)
personne = new Personne();
On peut faire de´claration + instanciation
let personne: Personne = new Personne();
Classe Syntaxe
TypeScript
Affectons les valeurs aux diffe´rents attributs
[Link] = 1;
[Link] = "wick";
[Link] = "john";
Pour eˆtre suˆr que les valeurs ont bien e´te´affecte´es aux attributs,
on affiche
[Link](personne);
// affiche Personne { num: 1, nom: 'wick', prenom: '
john' }
Classe Setter
TypeScript
Hypothese`
Supposant que l’on n’accepte pas de valeur ne´gative pour l’attribut num de la classe Personne
De´marche
Bloquer l’acce`s directe aux attributs (mettre la visibilite´ a`private)
De´finir des me´thodes publiques qui controˆlent l’affectation de valeurs aux attributs (les
setter)
Convention
Mettre la visibilite´ private ou protected pour tous les attributs
Mettre la visibilite´ public pour toutes les me´thodes
Classe Setter
TypeScript
Mettons la visibilite´ private pour tous les attributs de la classe
Personne
export class Personne{
private num : number;
private nom : string;
private prenom : string;
}
Dans le fichier [Link], les trois lignes suivantes sont souligne´es
en rouge
[Link] = 1;
[Link] = "wick";
[Link] = "john";
Classe Setter
TypeScript
Conventions TypeScript des setters
Le setter est une me´thode de´clare´e avec le mot-cle´ set.
Il porte le nom de l’attribut.
On l’utilise comme un attribut.
Pour e´viter l’ambigu¨ıte´, on pre´fixe l’attribut par un underscore.
Classe Setter
TypeScript
Nouveau contenu de la classe Personne apre`s ajout des setters
export class Personne{
private _num : number;
private _nom : string;
private _prenom : string;
public set num(num : number) {
this._num = (num >= 0 ? num : 0);
}
public set nom(nom: string)
{ this._nom = nom;
}
public set prenom(prenom: string)
{ this._prenom = prenom;
}
}
Classe Setter
TypeScript
Pour tester, rien à changer dans [Link]
import { Personne } from './personne';
let personne: Personne = new Personne();
[Link] = 1;
[Link] = "wick";
[Link] = "john";
[Link](personne);
Le resultat́ est :
Personne { num: 1, nom: ’wick’, prenom: ’john’ }
Classe Setter
TypeScript
Testons avec une valeur ne´gative pour l’attribut numero
import { Personne } from './personne';
let personne: Personne = new Personne();
[Link] = -1;
[Link] = "wick";
[Link] = "john";
[Link](personne);
Le resultat́ est :
Personne { num: 0, nom: ’wick’, prenom: ’john’ }
Classe Getter
TypeScript
Questio
n
Comment re´cupe´rer les attributs (prive´s) de la classe Personne?
Demarche´
De´finir des me´thodes qui retournent les valeurs des attributs (les getter)
Conventions TypeScript
Le getter est une me´thode de´clare´e avec le mot-cle´ get.
Il porte le nom de l’attribut.
On l’utilise comme un attribut.
Classe Getter
TypeScript
Ajoutons les getters dans la classe Personne
public get num() : number {
return this._num;
}
public get nom(): string {
return this._nom;
}
public get prenom(): string {
return this._prenom;
}
Classe Getter
TypeScript
Pour tester
import { Personne } from './personne';
let personne: Personne = new Personne();
[Link] = 1;
[Link] = "wick";
[Link] = "john";
[Link]([Link]);
// affiche 1
[Link]([Link]);
// affiche wick
[Link]([Link]);
// affiche john
Classe Constructeur
TypeScript
Remarques
Par de´faut, toute classe TypeScript a un constructeur par de´faut
sans parame`tre.
Pour simplifier la cre´ation d’objets, on peut de´finir un nouveau
constructeur qui prend en parame`tre plusieurs attributs de la
classe.
Les constructeurs avec TypeScript
On le de´clare avec le mot-cle´ constructor.
Il peut contenir la visibilite´ des attributs si on veut simplifier la
de´claration.
Classe Constructeur
TypeScript
Le constructeur de la classe Personne prenant trois parame`tres
public constructor(_num: number, _nom: string, _prenom: string)
{
this._num = _num;
this._nom = _nom;
this._prenom = _prenom;
}
Pour pre´server la cohe´rence, il faut que le constructeur controˆle la valeur de
l’attribut num
public constructor(_num: number, _nom: string, _prenom: string)
{
this._num = (_num >= 0 ? _num : 0);
this._nom = _nom;
this._prenom = _prenom;
}
Classe Constructeur
TypeScript
On peut aussi appelé le setter dans le constructeur
public constructor(_num: number, _nom: string,
_prenom: string) {
[Link] = _num;
this._nom = _nom;
this._prenom = _prenom;
}
Classe Constructeur
TypeScript
Dans [Link], la ligne suivante est soulignee´ en rouge
let personne: Personne = new Personne();
Explication
Le constructeur par de´faut a e´te´ e´crase´ (il n’existe plus)
Comment faire?
TypeScript n’autorise pas la pre´sence de plusieurs constructeurs (la surcharge)
On peut utiliser soit les valeurs par de´faut, soit les parame`tres optionnels
Classe Constructeur
TypeScript
Le nouveau constructeur avec les parame`tres optionnels
public constructor(_num?: number, _nom?: string,
_prenom?: string) {
if(_num)
[Link] = _num;
if (_nom)
this._nom = _nom;
if(_prenom)
this._prenom = _prenom;
}
Classe Constructeur
TypeScript
Pour tester
import { Personne } from './personne';
let personne: Personne = new Personne();
[Link] = -1;
[Link] = "wick";
[Link] = "john";
[Link](personne);
let personne2: Personne = new Personne(2, 'bob', 'mike');
[Link](personne2);
En executant,́ le resultat́ est :
Personne { num: 0, nom: ’wick’, prenom: ’john’ }
Personne { num: 2, nom: ’bob’, prenom: ’mike’ }
Classe Constructeur
TypeScript
TypeScript nous offre la possibilite´ de fusionner la de´claration des attributs et le
constructeur
public constructor(private _num : number = 0,
private _nom : string = "",
private _prenom : string = "") {
En executant,´ le resultat´ est le memeˆ
Personne { num: 0, nom: ’wick’, prenom: ’john’ }
Personne { num: 2, nom: ’bob’, prenom: ’mike’ }
Classe Attributs et me´thodes statiques
TypeScript
Exemple
Si on voulait cre´er un attribut contenant le nombre d’objets cre´e´s a`
partir de la classe Personne
Notre attribut doit eˆtre de´clare´static, sinon chaque objet
pourrait avoir sa propre valeur pour cet attribut
Classe Attributs et me´thodes statiques
TypeScript
Ajoutons un attribut statique nbrPersonnes a`la liste d’attributs de la
classe Personne
private static _nbrPersonnes: number = 0;
Incre´mentons notre compteur de personnes dans les constructeurs
public constructor(private _num: number = 0,
private _nom: string = "",
private _prenom: string = "") {
Personne._nbrPersonnes++;
}
Classe Attributs et me´thodes statiques
TypeScript
Cre´ons un getter pour l’attribut static nbrPersonnes
public static get nbrPersonnes() {
return Personne._nbrPersonnes;
}
Testons cela dans [Link]
import { Personne } from './personne';
[Link]([Link]);
// affiche 0
let personne: Personne = new Personne();
[Link] = -1;
[Link] = "wick";
[Link] = "john";
[Link]([Link]);
// affiche 1
let personne2: Personne = new Personne(2, 'bob', 'mike');
[Link]([Link]);
// affiche 2
Héritage
TypeScript
L’héritage, quand ?
Lorsque deux ou plusieurs classes partagent plusieurs attributs (et
me´thodes)
Lorsqu’une Classe1 est (une sorte de ) Classe2
Forme ge´ne´rale
class ClasseFille extends ClasseM`ere
{
// code
};
Héritage
TypeScript
Particularite´ du langage TypeScript
Une classe ne peut he´riter que d’une seule classe
L’he´ritage multiple est donc non-autorise´.
Héritage
TypeScript
Pre´parons la classe Enseignant
import { Personne } from "./personne";
export class Enseignant extends Personne {
Pre´parons la classe Etudiant
import { Personne } from "./personne";
export class Etudiant extends Personne {
extends est le mot-cle´ a`utiliser pour de´finir une relation d’he´ritage entre deux
classes
Héritage
TypeScript
Ensuite
Cre´er un attribut niveau dans la classe Etudiant ainsi que ses
getter et setter
Cre´er un attribut salaire dans la classe Enseignant ainsi que
ses getter et setter
Héritage
TypeScript
Pour cre´er un objet de type Enseignant
import { Enseignant } from './enseignant';
let enseignant: Enseignant = new Enseignant();
[Link] = 3;
[Link] = "green";
[Link] = "jonas";
[Link] = 1700;
[Link](enseignant);
En exe´cutant, le re´sultat est :
Enseignant { _num: 3, _nom: 'green', _prenom: 'jonas', _salaire
: 1700 }
Héritage
TypeScript autorise la rede´finition : on peut de´finir un constructeur, meˆme s’il
existe dans la classe me`re, qui prend plusieurs parame`tres et qui utilise le
constructeur de la classe me`re
constructor(_num?: number,
_nom?: string,
_prenom?: string,
_salaire?: number) {
super(_num, _nom, _prenom);
}
super() fait appel au constructeur de la classe me`re
Maintenant, on peut cre´er un enseignant ainsi
let enseignant: Enseignant = new Enseignant(3, "green", "jonas"
, 1700);
Héritage
TypeScript
A`partir de la classe Enseignant
On ne peut avoir acce`s direct a`un attribut de la classe me`re
C’est-a`-dire, on ne peut faire this. num car les attributs ont une
visibilite´ private
Pour modifier la valeur d’un attribut prive´ de la classe me`re, il faut
soit utiliser les getters/setters
soit mettre la visibilité des attributs de la classe mère à protected
Héritage
TypeScript
On peut cre´er un objet de la classe Enseignant ainsi
let enseignant: Enseignant = new Enseignant(3, "
green", "jonas", 1700);
Ou ainsi
let enseignant: Personne = new Enseignant(3, "green"
, "jonas", 1700);
Ceci est faux
let enseignant: Enseignant = new Personne(3, "green"
, "jonas");
Héritage
TypeScript
Remarque
Pour connaˆıtre la classe d’un objet, on peut utiliser le mot-cle´ instanceof
Exemple
let enseignant: Personne = new Enseignant(3, "green", "jonas",
1700);
[Link](enseignant instanceof Enseignant);
// affiche true
[Link](enseignant instanceof Personne);
// affiche true
[Link](personne instanceof Enseignant);
// affiche false
Héritage
TypeScript
Exercice
Cre´er un objet de type Etudiant, un deuxie`me de type Enseignant et un
dernier de type Personne stocker les tous dans un seul tableau.
Parcourir le tableau et afficher pour chacun soit le numero s’il est personne, soit
le salaire s’il est enseignant ou soit le niveau s’il est e´tudiant.
Héritage
TypeScript
Solution
let personnes: Array<Personne> = [personne,
enseignant, etudiant];
for(let p of personnes) {
if(p instanceof Enseignant)
[Link]([Link]);
else if (p instanceof Etudiant)
[Link]([Link])
else
[Link]([Link]);
}
Classe et me´thode abstraites
TypeScript
Classe abstraite
C’est une classe qu’on ne peut instancier
On la de´clare avec le mot-cle´ abstract
Si on de´clare la classe Personne abstraite
export abstract class Personne {
...
}
Tout ce code sera souligne´ en rouge
let personne: Personne = new Personne();
...
let personne2: Personne = new Personne(2, 'bob', 'mike');
Classe et me´thode abstraites
TypeScript
Méthode abstraite
C’est une me´thode non imple´mente´e (sans code)
Une me´thode abstraite doit eˆtre de´clare´e dans une classe abstraite
Une me´thode abstraite doit eˆtre imple´mente´e par les classes filles de la classe abstraite
De´clarons une me´thode abstraite afficherDetails() dans Personne
abstract afficherDetails(): void ;
Remarque
La me´thode afficherDetails() dans Personne est souligne´e en rouge car la classe
doit eˆtre de´clare´e abstraite
En de´clarant la classe Personne abstraite, les deux classes Etudiant et Enseignant
sont souligne´es en rouge car elles doivent imple´menter les me´thodes abstraites de
Classe et me´thode abstraites
Dans la classe Enseignant on ajoute :
afficherDetails(): void {
[Link](`Enseignant [${[Link]} ${[Link]}, salaire : $
{[Link]}]`);
}
Dans la classe Etudiant on ajoute :
afficherDetails(): void {
[Link](`Enseignant [${[Link]} ${[Link]}, niveau : $
{[Link]}]`);
}
Classe et me´thode abstraites
TypeScript
Pour tester
let enseignant: Enseignant = new Enseignant(3, "
green", "jonas", 1700);
[Link]();
En exe´cutant, le re´sultat est :
Enseignant [Green jonas, salaire : 1700]
Interface
TypeScript
En TypeScript
Une classe ne peut he´riter que d’une seule classe
Mais elle peut he´riter de plusieurs interfaces
Une interface
de´clare´e avec le mot-cle´ interface
comme une classe comple`tement abstraite (impossible de
l’instancier) dont : toutes les me´thodes sont abstraites
un protocole, un contrat : toute classe qui he´rite d’une interface
doit imple´menter toutes ses me´thodes
Interface
TypeScript
De´finissons l’interface IMiseEnForme dans [Link]
export interface IMiseEnForme {
afficherNomMajuscule(): void;
afficherPrenomMajuscule() : void;
}
Pour he´riter d’une interface, on utilise le mot-cle´ implements
export abstract class Personne implements IMiseEnForme {
...
}
Interface
TypeScript
Implémentant les deux me´thodes dans la classe personne
afficherNomMajuscule(): void {
[Link]([Link]());
}
afficherPrenomMajuscule(): void {
[Link]([Link]());
}
Interface
TypeScript
Pour tester
let enseignant: Enseignant = new Enseignant(3, "
green", "jonas", 1700);
[Link]();
[Link]();
En exe´cutant, le re´sultat est :
GREEN
JONAS
Interface
TypeScript
Remarque
Une interface peut he´riter de plusieurs autres interfaces (mais pas
d’une classe)
Pour cela, il faut utiliser le mot-cle´ extends et pas implements
car une interface n’imple´mente jamais de me´thodes.
Ge´ne´ricite´
TypeScript
Ge´ne´ricite´
Un concept de´fini dans tous les LOO avec < ... >
Elle permet de de´finir des fonctions, classes, interfaces qui
s’adaptent avec plusieurs types
Ge´ne´ricite´
TypeScript
Exemple
si on a besoin d’une classe dont les me´thodes effectuent les
meˆmes ope´rations quel que soit le type d’attributs
somme pour entiers ou re´els,
concate´nation pour chaˆınes de caracte`res,
ou logique pour boole´ens...
...
Impossible sans de´finir plusieurs classes (une pour chaque
type)
Ge´ne´ricite´
TypeScript
Solution avec la ge´ne´ricite´
export class Operation<T> {
constructor(private var1: T, private var2: T) { }
public plus() {
if (typeof this.var1 == 'string') {
return this.var1 + this.var2;
}
else if (typeof this.var1 == 'number' && typeof this.var2 == '
number') {
return this.var1 + this.var2;
}
else if (typeof this.var1 == 'boolean' && typeof this.var2 == '
boolean') {
return this.var1 || this.var2;
}
else {
throw "error"
}
}
}
Ge´ne´ricite´
TypeScript
Nous pouvons donc utiliser la meˆme me´thode qui fait la meˆme chose pour des types
diffe´rents
let operation1: Operation<number> = new Operation(5, 3);
[Link]([Link]());
// affiche 8
let operation2: Operation<string> = new Operation("bon", "jour");
[Link]([Link]());
// affiche bonjour
let operation3: Operation<number> = new Operation(5.2, 3.8);
[Link]([Link]());
// affiche 9
let operation4: Operation<boolean> = new Operation(true, false);
[Link]([Link]());
// affiche true