Modificadores de acceso en profundidad
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 39 de 91.
Ahora que entiendes los tres modificadores de acceso, exploremos cómo se comportan en situaciones de herencia. La idea clave es que los miembros protected se vuelven accesibles para las clases hijas, mientras que los miembros private permanecen ocultos incluso para las clases hijas.
<?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 causaría un error - ¡private!
// $this->getSerial() también fallaría - ¡método private!
}
}
$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();
Salida:
Toyota - V6La clase Car puede acceder a $brand (público) y llamar a getEngineInfo() (protegido), pero no tiene acceso a $serialNumber ni a getSerial() porque son privados de Vehicle. Esta distinción te permite compartir algunos detalles internos con las clases hijas, mientras mantienes otros completamente ocultos.
Punto clave: Usa protected cuando las clases secundarias necesiten acceder a datos o métodos internos, y private cuando ni siquiera las clases secundarias deban modificar ciertos detalles de implementación.
Desafío
FácilConstruyamos un sistema de gestión de dispositivos que explore cómo se comportan los modificadores de acceso en la herencia. Crearás una clase base Device con propiedades en distintos niveles de visibilidad y después la extenderás con una clase Smartphone que demuestre a qué miembros pueden y no pueden acceder las clases hijas.
Organizarás tu código en tres archivos:
Device.php: Crea una claseDeviceque represente dispositivos electrónicos con distintos niveles de sensibilidad de los datos. Incluye:- Una propiedad
public$brandpara el nombre del fabricante - Una propiedad
protected$modelNumberpara la identificación interna - Una propiedad
private$manufacturingCodepara datos exclusivos de la fábrica
privategetManufacturingCode()que devuelva el código de fabricación. Añade un métodopublicgetModelInfo()que devuelva"Model: [modelNumber]". Finalmente, añade un métodopublicgetFullCode()que devuelva"[brand]-[manufacturingCode]". Esto demuestra cómo la propia clase puede acceder a sus miembros privados.- Una propiedad
Smartphone.php: Crea una claseSmartphoneque extiendaDevice. Incluye el archivo Device. El constructor debe aceptar la marca, el número de modelo, el código de fabricación y el nombre de un sistema operativo. Llama al constructor padre con los tres primeros valores y después almacena el sistema operativo en una propiedad privada. Añade un método públicogetDeviceDetails()que devuelva"[brand] [modelNumber] running [os]". Observa que puedes acceder directamente a la propiedad pública$brandy a la propiedad protegida$modelNumber, pero no puedes acceder directamente a la propiedad privada$manufacturingCode: en su lugar, tendrías que usar el método público heredadogetFullCode().main.php: Incluye el archivo Smartphone. Recibirás cuatro entradas: un nombre de marca, un número de modelo, un código de fabricación y un sistema operativo. Crea una instancia deSmartphonecon estos valores. Imprime tres líneas:- El resultado de llamar a
getDeviceDetails() - El resultado de llamar al método heredado
getModelInfo() - El resultado de llamar al método heredado
getFullCode()
- El resultado de llamar a
Este desafío destaca la distinción clave: tu clase Smartphone puede usar libremente la propiedad protegida $modelNumber heredada de Device, pero la propiedad privada $manufacturingCode y el método getManufacturingCode() permanecen completamente ocultos: solo se puede acceder a ellos mediante la interfaz pública que Device decide exponer.
Pruébalo tú mismo
<?php
require_once 'Smartphone.php';
// Leer entradas
$brand = trim(fgets(STDIN));
$modelNumber = trim(fgets(STDIN));
$manufacturingCode = trim(fgets(STDIN));
$os = trim(fgets(STDIN));
// TODO: Crea una instancia de Smartphone con los valores de entrada
// TODO: Imprime el resultado de getDeviceDetails()
// TODO: Imprime el resultado del método heredado getModelInfo()
// TODO: Imprime el resultado del método heredado getFullCode()
?>Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - Calculadora de formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeRepaso: colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online