VISIBILIDAD ASIMÉTRICA EN PHP: QUÉ ES Y CÓMO FUNCIONA
La visibilidad asimétrica en php, introducida en php 8.4, es una nueva funcionalidad que permite definir diferentes niveles de visibilidad para los métodos de lectura (getter) y escritura (setter) de una propiedad en una clase. Esto significa que se puede controlar de manera más precisa cómo se accede a una propiedad para leerla o modificarla, utilizando diferentes modificadores de visibilidad (public, protected, private) para cada caso. La visibilidad asimétrica en php es ideal para frameworks o bibliotecas donde se necesita un control preciso sobre cómo se accede a las propiedades y facilita la creación de propiedades que solo pueden modificarse en ciertos contextos, como durante la inicialización de un objeto.¿Qué es la visibilidad asimétrica?
Tradicionalmente en php, una propiedad tiene un solo modificador de visibilidad que aplica tanto a la lectura como a la escritura. Por ejemplo, una propiedad public puede ser leída y modificada desde cualquier lugar, mientras que una private solo puede ser accedida dentro de la clase. Con la visibilidad asimétrica, se puede especificar una visibilidad para leer la propiedad y definir otra visibilidad diferente para escribir en la propiedad. Esto es especialmente útil para escenarios donde se quiere permitir un acceso amplio para leer una propiedad, pero restringir quién puede modificarla, o viceversa. La visibilidad asimétrica se implementa utilizando la nueva sintaxis set y get en la declaración de propiedades. La estructura general es:
class Clase {
public private(set) $propiedad;
}
- public: Define la visibilidad para lectura (get).
- private(set): Define la visibilidad para escritura (set).
En este ejemplo, $propiedad puede ser leída desde cualquier lugar (public), pero solo puede ser modificada dentro de la clase (private).
Ejemplo práctico:
class Usuario {
public private(set) string $nombre;
public function __construct(string $nombre) {
$this->nombre = $nombre; // Escritura permitida dentro de la clase
}
}
$usuario = new Usuario("Juan");
echo $usuario->nombre; // Lectura: OK (public)
$usuario->nombre = "Ana"; // Error: No se puede modificar fuera de la clase (private(set))
En este caso la propiedad $nombre es pública para lectura, por lo que cualquier código puede acceder a su valor y la propiedad es privada para escritura, por lo que solo los métodos dentro de la clase Usuario pueden modificarla.
Combinaciones posibles
Se puede usar cualquier combinación de modificadores de visibilidad (public, protected, private) para get y set.
- Pública para lectura, protegida para escritura:
class Ejemplo {
public protected(set) string $dato;
}
- Lectura: Accesible desde cualquier lugar.
- Escritura: Solo accesible dentro de la clase y sus clases hijas.
- Protegida para lectura, privada para escritura:
class Ejemplo {
protected private(set) string $dato;
}
- Lectura: Solo accesible dentro de la clase y sus clases hijas.
- Escritura: Solo accesible dentro de la clase..
Ejemplo más complejo
class CuentaBancaria {
public private(set) float $saldo;
protected private(set) string $titular;
public function __construct(string $titular, float $saldoInicial) {
$this->titular = $titular; // Escritura permitida (dentro de la clase)
$this->saldo = $saldoInicial; // Escritura permitida (dentro de la clase)
}
public function depositar(float $monto): void {
$this->saldo += $monto; // Escritura permitida (dentro de la clase)
}
}
class CuentaPremium extends CuentaBancaria {
public function verTitular(): string {
return $this->titular; // Lectura permitida (protected)
}
}
$cuenta = new CuentaBancaria("Ana", 1000.0);
echo $cuenta->saldo; // OK: 1000.0 (lectura pública)
$cuenta->saldo = 2000.0; // Error: Escritura restringida (private(set))
$cuenta->depositar(500.0); // OK: Modifica saldo internamente
echo $cuenta->saldo; // OK: 1500.0
$premium = new CuentaPremium("Juan", 5000.0);
echo $premium->verTitular(); // OK: "Juan" (lectura protegida en clase hija)
// echo $cuenta->titular; // Error: No accesible fuera de la clase o clases hijas
class Clase {
public private(set) $propiedad;
}
class Usuario {
public private(set) string $nombre;
public function __construct(string $nombre) {
$this->nombre = $nombre; // Escritura permitida dentro de la clase
}
}
$usuario = new Usuario("Juan");
echo $usuario->nombre; // Lectura: OK (public)
$usuario->nombre = "Ana"; // Error: No se puede modificar fuera de la clase (private(set))
- Pública para lectura, protegida para escritura:
class Ejemplo { public protected(set) string $dato; }- Lectura: Accesible desde cualquier lugar.
- Escritura: Solo accesible dentro de la clase y sus clases hijas.
- Protegida para lectura, privada para escritura:
class Ejemplo { protected private(set) string $dato; }- Lectura: Solo accesible dentro de la clase y sus clases hijas.
- Escritura: Solo accesible dentro de la clase..
class CuentaBancaria {
public private(set) float $saldo;
protected private(set) string $titular;
public function __construct(string $titular, float $saldoInicial) {
$this->titular = $titular; // Escritura permitida (dentro de la clase)
$this->saldo = $saldoInicial; // Escritura permitida (dentro de la clase)
}
public function depositar(float $monto): void {
$this->saldo += $monto; // Escritura permitida (dentro de la clase)
}
}
class CuentaPremium extends CuentaBancaria {
public function verTitular(): string {
return $this->titular; // Lectura permitida (protected)
}
}
$cuenta = new CuentaBancaria("Ana", 1000.0);
echo $cuenta->saldo; // OK: 1000.0 (lectura pública)
$cuenta->saldo = 2000.0; // Error: Escritura restringida (private(set))
$cuenta->depositar(500.0); // OK: Modifica saldo internamente
echo $cuenta->saldo; // OK: 1500.0
$premium = new CuentaPremium("Juan", 5000.0);
echo $premium->verTitular(); // OK: "Juan" (lectura protegida en clase hija)
// echo $cuenta->titular; // Error: No accesible fuera de la clase o clases hijas