Modificateurs d'accès en détail
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 39 sur 91.
Maintenant que vous comprenez les trois modificateurs d'accès, explorons comment ils se comportent dans les scénarios d'héritage. L'idée clé est que les membres protected deviennent accessibles aux classes enfants, tandis que les membres private restent cachés même pour les enfants.
<?php
class Vehicle {
public $brand;
protected $engineType;
private $serialNumber;
public function __construct($brand, $engine, $serial) {
$this->brand = $brand;
$this->engineType = $engine;
$this->serialNumber = $serial;
}
private function getSerial() {
return $this->serialNumber;
}
protected function getEngineInfo() {
return $this->engineType;
}
}
class Car extends Vehicle {
public function getDetails() {
return $this->brand . " - " . $this->getEngineInfo();
// $this->serialNumber provoquerait une erreur - privé !
// $this->getSerial() échouerait également - méthode privée !
}
}
$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();
Sortie :
Toyota - V6La classe Car peut accéder à $brand (public) et appeler getEngineInfo() (protégée), mais n'a pas accès à $serialNumber ou getSerial() car ils sont privés pour Vehicle. Cette distinction vous permet de partager certains détails internes avec les classes enfants tout en gardant les autres complètement cachés.
Point clé : Utilisez protected lorsque les classes enfants ont besoin d'accéder à des données ou des méthodes internes, et private lorsque même les classes enfants ne devraient pas toucher à certains détails d'implémentation.
Défi
FacileConstruisons un système de gestion d'appareils qui explore le comportement des modificateurs d'accès à travers l'héritage. Vous allez créer une classe de base Device avec des propriétés à différents niveaux de visibilité, puis l'étendre avec une classe Smartphone qui démontre quels membres les classes enfants peuvent ou ne peuvent pas accéder.
Vous organiserez votre code sur trois fichiers :
Device.php— Créez une classeDevicequi représente des appareils électroniques avec différents niveaux de sensibilité des données. Incluez :- Une propriété
public$brandpour le nom du fabricant - Une propriété
protected$modelNumberpour l'identification interne - Une propriété
private$manufacturingCodepour les données réservées à l'usine
privategetManufacturingCode()qui retourne le code de fabrication. Ajoutez une méthodepublicgetModelInfo()qui retourne"Model: [modelNumber]". Enfin, ajoutez une méthodepublicgetFullCode()qui retourne"[brand]-[manufacturingCode]"— cela démontre comment la classe elle-même peut accéder à ses propres membres privés.- Une propriété
Smartphone.php— Créez une classeSmartphonequi étendDevice. Incluez le fichier Device. Le constructeur doit accepter la marque, le numéro de modèle, le code de fabrication et un nom de système d'exploitation. Appelez le constructeur parent avec les trois premières valeurs, puis stockez l'OS dans une propriété privée. Ajoutez une méthode publiquegetDeviceDetails()qui retourne"[brand] [modelNumber] running [os]". Remarquez comment vous pouvez accéder directement au$brandpublic et au$modelNumberprotégé, mais vous ne pouvez pas accéder directement au$manufacturingCodeprivé — vous devrez utiliser la méthode publique héritéegetFullCode()à la place.main.php— Incluez le fichier Smartphone. Vous recevrez quatre entrées : un nom de marque, un numéro de modèle, un code de fabrication et un système d'exploitation. Créez une instance deSmartphoneavec ces valeurs. Affichez trois lignes :- Le résultat de l'appel à
getDeviceDetails() - Le résultat de l'appel à la méthode héritée
getModelInfo() - Le résultat de l'appel à la méthode héritée
getFullCode()
- Le résultat de l'appel à
Ce défi met en évidence la distinction clé : votre classe Smartphone peut utiliser librement le $modelNumber protégé hérité de Device, mais le $manufacturingCode privé et getManufacturingCode() restent complètement cachés — accessibles uniquement via l'interface publique que Device choisit d'exposer.
Aide-mémoire
Dans l'héritage, les membres protected sont accessibles aux classes enfants, tandis que les membres private restent cachés même pour les enfants.
<?php
class Vehicle {
public $brand;
protected $engineType;
private $serialNumber;
public function __construct($brand, $engine, $serial) {
$this->brand = $brand;
$this->engineType = $engine;
$this->serialNumber = $serial;
}
private function getSerial() {
return $this->serialNumber;
}
protected function getEngineInfo() {
return $this->engineType;
}
}
class Car extends Vehicle {
public function getDetails() {
return $this->brand . " - " . $this->getEngineInfo();
// $this->serialNumber provoquerait une erreur - private !
// $this->getSerial() échouerait également - méthode privée !
}
}
$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails(); // Toyota - V6
Les classes enfants peuvent accéder à :
- aux propriétés et méthodes
public - aux propriétés et méthodes
protected
Les classes enfants ne peuvent pas accéder à :
- aux propriétés et méthodes
private(celles-ci restent exclusives à la classe parente)
Bonne pratique : Utilisez protected lorsque les classes enfants ont besoin d'accéder à des données ou des méthodes internes, et private lorsque même les classes enfants ne devraient pas toucher à certains détails d'implémentation.
Essayez vous-même
<?php
require_once 'Smartphone.php';
// Lire les entrées
$brand = trim(fgets(STDIN));
$modelNumber = trim(fgets(STDIN));
$manufacturingCode = trim(fgets(STDIN));
$os = trim(fgets(STDIN));
// TODO: Créer une instance de Smartphone avec les valeurs d'entrée
// TODO: Afficher le résultat de getDeviceDetails()
// TODO: Afficher le résultat de la méthode héritée getModelInfo()
// TODO: Afficher le résultat de la méthode héritée getFullCode()
?>Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie