Cómo usar propiedades de solo lectura en PHP 8.1 – CloudSavvy IT

Logotipo de PHP

PHP 8.1 agrega soporte para un readonly modificador en las propiedades de la clase. Una propiedad etiquetada de esta manera solo se puede establecer una vez. Intentar cambiar el valor de una propiedad de solo lectura después de la inicialización arrojará un error.

«Solo lectura» es un término bastante vago, con diversas implicaciones en los lenguajes de programación individuales. En este contexto, «solo lectura» realmente significa «inmutable»: puede establecer el valor de una propiedad, pero no se puede cambiar después.

Escribir propiedades de solo lectura

Añade el readonly modificador para hacer una propiedad de solo lectura. Debe colocarse entre el modificador de acceso de la propiedad y su sugerencia de tipo.

class Demo {
 
    public string $Mutable;
 
    public readonly string $Immutable;
 
    public function __construct(
        string $Mutable,
        string $Immutable) {
 
        $this -> Mutable = $Mutable;
        $this -> Immutable = $Immutable;
    }
 
}

$Mutable es una propiedad pública regular. Puede cambiar su valor en cualquier momento, ya sea dentro de los métodos de la clase o desde fuera:

$demo = new Demo("A", "X");
$demo -> Mutable = "B";

$Immutable es un poco diferente. Todavía puede leer su valor cuando lo desee, pero cualquier modificación fallará con un Error:

// Throws an Error
$demo -> Immutable = "Y";

El readonly El modificador también se admite en propiedades de constructor promocionadas:

class Demo {
    public function __construct(
        public readonly string $Immutable="foobar"
    ) {}
}

Aún puede establecer la propiedad manualmente en su constructor cuando usa la promoción con un valor predeterminado. Es el parámetro de función que recibe el valor predeterminado, no la instancia de propiedad. La promoción tiene el mismo código que se muestra en el ejemplo anterior.

Advertencias

Las propiedades de solo lectura son una mejora de sintaxis sencilla que puede adoptar en su tiempo libre. No hay implicaciones de compatibilidad con versiones anteriores y su uso es completamente opcional. Si comienza a agregarlos, hay algunas advertencias y limitaciones que debe tener en cuenta.

A diferencia de las propiedades normales, las propiedades de solo lectura no pueden tener un valor predeterminado en su definición:

class Demo {
    protected readonly string $foo = "bar";
}

Esta declaración define e inicializa $foo. No puede cambiar su valor después de la inicialización, por lo que la propiedad es efectivamente una constante. Como resultado, los valores predeterminados están prohibidos y, en su lugar, debe usar una constante real:

class Demo {
    const foo = "bar";
}

Siguiendo esta restricción, readonly es solamente compatible con propiedades escritas. La siguiente propiedad tiene una definición ilegal:

class Demo {
    protected readonly $foo;
}

Una propiedad sin tipo, como $foo anterior, tiene un valor predeterminado implícito de null. Si readonly fuera permitido, la regla de “no constantes implícitas” resurgiría. Las propiedades con tipo distinguen entre estados «no inicializado» y «nulo», por lo que existen sin ningún valor hasta que establezca uno explícitamente.

El modificador de solo lectura tiene reglas especiales cuando se usa como parte de la herencia de clases. Las clases secundarias no pueden agregar ni quitar readonly en propiedades definidas por sus padres.

Hacer una propiedad de escritura readonly rompería la clase padre si sus métodos mutaran el valor. Si bien eliminar la restricción es aparentemente inofensivo, las opiniones de RFC readonly como una “restricción intencional” de capacidades que se perderían si se permitieran las invalidaciones de herencia. Está prohibido para que las clases de padres puedan afirmar que los niños no pueden causar efectos secundarios modificando propiedades que están destinadas a ser de solo lectura.

Las propiedades de solo lectura solo se pueden establecer dentro del ámbito en el que están definidas. Esto significa que public las propiedades no se pueden establecer desde fuera de una clase, incluso si no se han inicializado previamente:

class Demo {
    public readonly string $foo;
}
 
$d = new Demo();
$d -> foo = "bar";  // illegal

La inicialización debe ocurrir dentro de la clase que define la propiedad. Como resultado, las propiedades de solo lectura están más cerca de los campos inmutables de otros lenguajes de programación en contraposición a las propiedades PHP preexistentes.

El readonly El modificador se aplica igualmente a todas las escrituras. No distingue entre acceso interno y externo. No puede tener una propiedad que sea de solo lectura pública pero que se pueda escribir dentro de la clase, aunque una futura extensión de especificación podría permitirlo.

Un problema final se refiere a la clone palabra clave. Este código no funcionará:

class Demo {
    public function __construct(
        public string $foo
    ) {}
}
 
$d = new Demo("bar");
$d2 = clone $d;
$d2 -> foo = "foobar";

La clonación sigue las mismas reglas que los accesos regulares a la propiedad. Aunque el cambio a foobar es la primera vez que foo se accede en $d2, la propiedad ya ha sido inicializada por el proceso de clonación. Hay una inicialización implícita durante el clon.

¿Cuándo usar propiedades de solo lectura?

Las propiedades de solo lectura acelerarán significativamente la creación de clases simples, que representan estructuras de datos. Es común escribir clases desechables para contener parámetros de solicitud HTTP, objetos de transferencia de datos y datos de respuesta. Por lo general, son inmutables, donde no se espera que las propiedades cambien después de que se construya la clase.

Anteriormente, tenía dos opciones poco atractivas al escribir clases tipo estructura: usar propiedades públicas, acelerar el desarrollo pero permitir modificaciones, o dedicar tiempo a agregar manualmente métodos getter para exponer propiedades protegidas.

// Not ideal - Properties could be modified externally
class UserCreationRequest {
    public function __construct(
        public string $Username,
        public string $Password
    ) {}
}
 
// Not ideal either - Lots of boilerplate code
class UserCreationRequest {
    public function __construct(
        protected string $Username,
        protected string $Password
    ) {}
 
    public function getUsername() : string {
        return $this -> Username;
    }
 
    public function getPassword() : string {
        return $this -> Password;
    }
}

Las propiedades de solo lectura finalmente hacen posible el enfoque ideal:

class UserCreationRequest {
    public function __construct(
        public readonly string $Username,
        public readonly string $Password
    ) {}
}

Las propiedades son de acceso público pero inmutables. En combinación con la promoción de propiedades del constructor, las propiedades de solo lectura prometen reducir significativamente el código estándar, lo que le permite escribir clases útiles más rápidamente.

readonly también ayuda a la legibilidad del código e indica mejor sus intenciones. Cualquiera que lea o edite el UserCreationRequest La clase sabe que sus propiedades no están destinadas a cambiar. En el primer ejemplo, se desconoce si otro código del proyecto modifica las propiedades de la clase directamente. El segundo ejemplo es un poco más claro, pero aún podría inducir a un desarrollador a implementar redundantes setUsername() y setPassword() métodos.

Conclusión

El readonly El modificador brinda soporte de inmutabilidad incorporado a las propiedades de la clase PHP. Hace que su código sea más claro y evita cambios de valor involuntarios al imponer la inmutabilidad en tiempo de ejecución.

Mirando hacia atrás a la serie de versiones de PHP 7, creando una clase básica similar a una estructura utilizada para involucrar la definición de propiedades escritas, escribir un constructor que establezca esas propiedades y luego agregar métodos getter para exponer sus valores. Con PHP 8.1, puede condensar todo eso en una sola firma de constructor combinando public readonly y promoción inmobiliaria.

Propiedades de solo lectura son implementados en las últimas versiones de desarrollo de PHP 8.1. El lanzamiento listo para producción llegará en noviembre de 2021.

Deja un comentario

En esta web usamos cookies para personalizar tu experiencia de usuario.    Política de cookies
Privacidad