BaliseTonSite

Classes & POO

La programmation orientée objet, version TypeScript.

5.1Classes de base

TypeScripttypescript
class Utilisateur {
  nom: string
  email: string
  age: number

  constructor(nom: string, email: string, age: number) {
    this.nom = nom
    this.email = email
    this.age = age
  }

  sePresenter(): string {
    return `Je suis ${this.nom}, j'ai ${this.age} ans.`
  }
}

const alice = new Utilisateur("Alice", "alice@email.com", 25)
console.log(alice.sePresenter())  // "Je suis Alice, j'ai 25 ans."
console.log(alice.nom)            // "Alice"

5.2Modificateurs d'accès

C'est LE gros ajout de TypeScript par rapport à JavaScript. Trois niveaux de visibilité :

TypeScripttypescript
class CompteBancaire {
  public titulaire: string       // ← Accessible partout (défaut)
  private solde: number          // ← Accessible seulement dans la classe
  protected banque: string       // ← Accessible dans la classe et ses enfants

  constructor(titulaire: string, solde: number) {
    this.titulaire = titulaire
    this.solde = solde
    this.banque = "BanqueTS"
  }

  // Méthode publique pour accéder au solde
  public consulterSolde(): string {
    return `Solde de ${this.titulaire} : ${this.solde}€`
  }

  // Méthode pour modifier le solde de façon contrôlée
  public deposer(montant: number): void {
    if (montant <= 0) throw new Error("Montant invalide")
    this.solde += montant
  }
}

const compte = new CompteBancaire("Alice", 1000)
compte.titulaire       // ✅ Public
// compte.solde         // ❌ Erreur : 'solde' est privé
compte.consulterSolde() // ✅ "Solde de Alice : 1000€"
TypeScripttypescript
// Version courte - les paramètres deviennent automatiquement des propriétés
class Produit {
  constructor(
    public nom: string,
    public prix: number,
    private stock: number = 0
  ) {}
  // Plus besoin de this.nom = nom, etc.

  acheter(quantite: number): boolean {
    if (quantite > this.stock) return false
    this.stock -= quantite
    return true
  }
}

const laptop = new Produit("MacBook", 2499, 10)
console.log(laptop.nom)    // ✅ "MacBook"
// console.log(laptop.stock) // ❌ Privé

5.3Héritage

TypeScripttypescript
class Animal {
  constructor(
    public nom: string,
    protected son: string
  ) {}

  faireDuBruit(): string {
    return `${this.nom} fait : ${this.son}`
  }
}

class Chien extends Animal {
  constructor(nom: string) {
    super(nom, "Woof !")  // Appelle le constructeur parent
  }

  rapporter(objet: string): string {
    return `${this.nom} rapporte ${objet} !`
  }
}

class Chat extends Animal {
  constructor(nom: string) {
    super(nom, "Miaou !")
  }

  ronronner(): string {
    return `${this.nom} ronronne...`
  }
}

const rex = new Chien("Rex")
rex.faireDuBruit()     // "Rex fait : Woof !"
rex.rapporter("balle") // "Rex rapporte balle !"

const minou = new Chat("Minou")
minou.faireDuBruit()   // "Minou fait : Miaou !"
minou.ronronner()      // "Minou ronronne..."

5.4Classes abstraites

Une classe abstraite ne peut pas être instanciée directement. Elle sert de plan obligatoire pour les classes enfants :

TypeScripttypescript
abstract class Forme {
  abstract aire(): number        // ← Les enfants DOIVENT implémenter
  abstract perimetre(): number   // ← Les enfants DOIVENT implémenter

  // Méthode concrète partagée
  description(): string {
    return `Aire: ${this.aire().toFixed(2)}, Périmètre: ${this.perimetre().toFixed(2)}`
  }
}

class Cercle extends Forme {
  constructor(private rayon: number) {
    super()
  }

  aire(): number {
    return Math.PI * this.rayon ** 2
  }

  perimetre(): number {
    return 2 * Math.PI * this.rayon
  }
}

class Rectangle extends Forme {
  constructor(
    private largeur: number,
    private hauteur: number
  ) {
    super()
  }

  aire(): number {
    return this.largeur * this.hauteur
  }

  perimetre(): number {
    return 2 * (this.largeur + this.hauteur)
  }
}

// const forme = new Forme()   // ❌ Impossible : classe abstraite
const cercle = new Cercle(5)
console.log(cercle.description())    // "Aire: 78.54, Périmètre: 31.42"

5.5Implémenter des interfaces

TypeScripttypescript
interface Serializable {
  toJSON(): string
}

interface Validable {
  estValide(): boolean
}

// Une classe peut implémenter PLUSIEURS interfaces
class Formulaire implements Serializable, Validable {
  constructor(
    private champs: Record<string, string>
  ) {}

  toJSON(): string {
    return JSON.stringify(this.champs)
  }

  estValide(): boolean {
    return Object.values(this.champs).every(v => v.length > 0)
  }
}

const form = new Formulaire({ nom: "Alice", email: "alice@email.com" })
form.estValide()  // true
form.toJSON()     // '{"nom":"Alice","email":"alice@email.com"}'

5.6Getters et Setters

TypeScripttypescript
class Temperature {
  private _celsius: number

  constructor(celsius: number) {
    this._celsius = celsius
  }

  // Getter : accéder comme une propriété
  get celsius(): number {
    return this._celsius
  }

  get fahrenheit(): number {
    return this._celsius * 9/5 + 32
  }

  // Setter : modifier avec validation
  set celsius(valeur: number) {
    if (valeur < -273.15) {
      throw new Error("En dessous du zéro absolu !")
    }
    this._celsius = valeur
  }
}

const temp = new Temperature(25)
console.log(temp.celsius)      // 25 (getter)
console.log(temp.fahrenheit)   // 77 (getter calculé)

temp.celsius = 100             // setter avec validation
// temp.celsius = -300          // ❌ Erreur !

Verifie tes acquis

3 questions pour valider ce chapitre

1. Quelle est la difference entre private et protected ?

Valide et sauvegarde ce chapitre

Ne perds pas le fil de ton apprentissage. Chaque QCM terminé sauvegarde ton score. Crée ton profil gratuitement pour débloquer toutes les évaluations du site et retrouver tes résultats plus tard.

Commencer l'aventure
Déjà membre ?Connecte-toi