Menu
Coddy logo textTech

Modificadores de acceso a fondo

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 escenarios 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 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 - ¡privado!
        // $this->getSerial() también fallaría - ¡método privado!
    }
}

$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails();

Resultado:

Toyota - V6

La clase Car puede acceder a $brand (público) y llamar a getEngineInfo() (protegido), pero no tiene acceso a $serialNumber o getSerial() porque son privados para 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 hijas necesiten acceso a datos o métodos internos, y private cuando incluso las clases hijas no deban tocar ciertos detalles de implementación.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de gestión de dispositivos que explore cómo se comportan los modificadores de acceso a través de la herencia. Crearás una clase base Device con propiedades en diferentes niveles de visibilidad, y luego 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 clase Device que represente dispositivos electrónicos con diferentes niveles de sensibilidad de datos. Incluye:
    • Una propiedad public $brand para el nombre del fabricante
    • Una propiedad protected $modelNumber para identificación interna
    • Una propiedad private $manufacturingCode para datos exclusivos de fábrica
    El constructor debe aceptar los tres valores. Añade un método private getManufacturingCode() que devuelva el código de fabricación. Añade un método public getModelInfo() que devuelva "Model: [modelNumber]". Finalmente, añade un método public getFullCode() que devuelva "[brand]-[manufacturingCode]" — esto demuestra cómo la propia clase puede acceder a sus propios miembros privados.
  • Smartphone.php — Crea una clase Smartphone que extienda de Device. Incluye el archivo Device. El constructor debe aceptar brand, modelNumber, manufacturingCode y un nombre de sistema operativo. Llama al constructor padre con los tres primeros valores, luego almacena el OS en una propiedad privada. Añade un método público getDeviceDetails() que devuelva "[brand] [modelNumber] running [os]". Observa cómo puedes acceder directamente al $brand público y al $modelNumber protegido, pero no puedes acceder directamente al $manufacturingCode privado — en su lugar, tendrías que usar el método público heredado getFullCode().
  • 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 de Smartphone con 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()

Este desafío resalta la distinción clave: tu clase Smartphone puede usar libremente el $modelNumber protegido heredado de Device, pero el $manufacturingCode privado y getManufacturingCode() permanecen completamente ocultos — accesibles solo a través de la interfaz pública que Device decide exponer.

Hoja de referencia

En la herencia, los miembros protected son accesibles para las clases hijas, mientras que los miembros private permanecen ocultos incluso para las 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 - ¡privado!
        // $this->getSerial() también fallaría - ¡método privado!
    }
}

$car = new Car("Toyota", "V6", "ABC123");
echo $car->getDetails(); // Toyota - V6

Las clases hijas pueden acceder a:

  • propiedades y métodos public
  • propiedades y métodos protected

Las clases hijas no pueden acceder a:

  • propiedades y métodos private (estos permanecen exclusivos de la clase padre)

Mejor práctica: Use protected cuando las clases hijas necesiten acceso a datos o métodos internos, y private cuando incluso las clases hijas no deban tocar ciertos detalles de implementación.

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: Crear una instancia de Smartphone con los valores de entrada

// TODO: Imprimir el resultado de getDeviceDetails()

// TODO: Imprimir el resultado del método heredado getModelInfo()

// TODO: Imprimir el resultado del método heredado getFullCode()
?>
quiz iconPonte a prueba

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