Tecnología

Cómo los nuevos tipos de intersección en PHP 8.1 le brindan más flexibilidad – CloudSavvy IT

8 nuevas funciones principales en PHP 8 - CloudSavvy IT

Logotipo de PHP

Los tipos de intersección son una nueva característica del sistema de tipos que viene en PHP 8.1. Le permiten escribir valores de sugerencia que deben satisfacer más de una restricción de tipo. PHP ya tiene tipos de unión que combinan tipos con una cláusula «o» lógica; los tipos de intersección ofrecen una cláusula «y» en su lugar.

Algunos desarrolladores ya mecanografían intersecciones utilizando anotaciones PHPDoc. La incorporación de soporte nativo es un paso adelante, ya que los tipos se aplicarán en tiempo de ejecución. También son totalmente compatibles con la herencia de clases, lo que ayuda a reducir el riesgo de errores debido a anotaciones obsoletas o incompatibles.

Sintaxis básica

La sintaxis del tipo de intersección es similar a la de los tipos de unión:

class DemoClass {
 
    public Countable|Stringable $Union;
 
    public Countable&Stringable $Intersection;
 
}

En este ejemplo, $Union será satisfecho por cualquier valor que sea ya sea Countable o Stringable. $Intersection solo aceptará valores que cumplan ambas cosas las limitaciones. Obtendrás un TypeError si asigna a la propiedad un valor que implementa uno o cero de los tipos sugeridos.

Los tipos de intersección se admiten en todos los lugares donde funcionan las sugerencias tipográficas. Puede utilizarlos con definiciones de propiedades, parámetros de funciones y valores de retorno.

A diferencia de los tipos de unión, las intersecciones solo pueden insinuar interfaces y clases. Una intersección escalar como int&string no tiene sentido, ya que nunca podría satisfacerse. La mixed type también está prohibido, porque cada valor satisfará su restricción.

Variación de tipo

Los tipos de intersección respetan las reglas de variación existentes de PHP. Los tipos de retorno de los métodos anulados deben ser covariantes, mientras que los tipos de parámetros son contravariantes. Las propiedades de la clase son siempre invariantes, por lo que los niños no pueden cambiar la definición de tipo a menos que la nueva firma sea tanto un subtipo como un supertipo de la heredada.

Para los valores de retorno, las reglas de varianza significan que puede agregar tipos de intersección adicionales en métodos anulados. Los métodos también pueden eliminar, pero no agregar, tipos a las intersecciones utilizadas como parámetros. Estas reglas refuerzan el principio de sustitución de Liskov.

interface I1 {
    public function method1(A&B $demo) : X&Y;
    public function method2(A&B $demo) : X&Y;
}
 
interface I2 extends I1 {
 
    // ALLOWED
    public function method1(A $demo) : X&Y&Z;
 
    // NOT ALLOWED
    public function method2(A&B&C $demo) : X;
 
}

En el caso de method1, las restricciones en realidad no han cambiado. Está indicando que el método anulado puede funcionar con cualquier A, incluso si no es también un X. Es menos específico, lo que da como resultado una variación de parámetro aceptable. La declaración de devolución es más específico, indicando el valor que implementará X, Y y Z; En este escenario, agregar especificidad no rompe el contrato, ya que el valor aún será aceptado por cualquier cosa que insinúe. I1.

La method2 la anulación está rota en ambos aspectos. Al requerir que el parámetro de entrada satisfaga A, B y C, ya no es un reemplazo directo de I1. Similar, method2 solo garantiza que el valor de retorno será una instancia de X. Esto rompe el contrato como cualquier insinuación I1 requiere el valor para satisfacer la intersección de X y Y.

Las intersecciones invierten las reglas prácticas de varianza de los tipos de unión. Como las uniones se combinan usando «o», los niños pueden agregar tipos de parámetros y eliminar tipos de retorno. El principio de sustitución de Liskov se satisface cuando se invierte el efecto de ampliación y reducción de las restricciones de tipo.

Al igual que con los tipos de unión, las reglas de variación también se aplican a los tipos que componen una intersección: ese es el individuo X y Y partes de X&Y. Puede limitar un tipo al devolverlo, indicando que devolverá una subclase, o ampliarlo como parámetro, aceptando una superclase.

Las intersecciones también poseen algunas reglas especiales sobre aliasing e implementaciones concretas. Si escribe una sugerencia X&Y pero escribe una interfaz Z extends X, Y, es lógico que Z satisface la restricción. En consecuencia, puede escribir sugerencias Z en vez de X&Y siempre que se permita la covarianza:

interface Test extends X, Y {}
 
interface Demo1 {
    public function demo() : X&Y;
}
 
interface Demo2 {
    public function demo() : Test;
}

Esto le permite teclear una clase o interfaz concreta si depende de una funcionalidad adicional. Es aceptable siempre que todas las restricciones de la intersección se satisfagan con la sugerencia de tipo final.

¿Cuándo utilizar los tipos de intersección?

Los tipos de intersección son para los momentos en los que desea asegurarse de que un valor satisfaga una interfaz compuesta sin definir realmente esa interfaz. Las versiones anteriores de PHP no proporcionaban ningún soporte nativo para esto, por lo que necesitaba agregar un montón de texto estándar adicional a su base de código:

interface CountableStringable extends Countable, Stringable {
    // ...
}
 
class FakeArray implements CountableStringable {
 
    public array $items = [];
 
    public function count() : int {
        return count($this -> items);
    }
 
    public function __toString() : string {
        return implode(", ", $this -> items);
    }
 
}
 
class DemoClass {
 
    public CountableStringable $Value;
 
}

Esto conduce a un exceso de interfaces superficiales en forma de trozos para lograr un comportamiento de intersección básico. Aunque los desarrolladores de PHP han sobrevivido sin intersecciones hasta la fecha, su presencia ayuda a solidificar las capacidades compuestas del sistema de tipos. El uso de intersecciones nativas crea un código más limpio e intuitivo.

¿Qué pasa con los tipos compuestos?

No es posible combinar tipos de intersección y unión en la misma sugerencia de tipo. Si bien sería técnicamente posible, se ha omitido del RFC actual ya que existen ambigüedades en torno a la sintaxis, la precedencia y la varianza.

Los tipos compuestos siguen siendo una idea para el futuro. Si se agregan, podría comenzar a agregar sugerencias tipográficas complejas como esta:

class DemoClass {
 
    public Countable&Stringable|CountableStringable $Intersection;
 
}

Esta clase de ejemplo combina las dos implementaciones anteriores. Si funcionara, le permitiría adoptar tipos de intersección nativos y al mismo tiempo conservar la compatibilidad con clases anteriores utilizando el enfoque «falso».

Los tipos compuestos completos completarían el manejo de tipos múltiples facilitado por uniones e intersecciones. Mientras tanto, deberá seguir escribiendo sus propias interfaces compuestas en estos escenarios.

Resumen

Los tipos de intersección están llegando a PHP 8.1 y desbloquearán posibilidades más avanzadas dentro del sistema de tipos. La ampliación de las opciones en torno a los tipos compuestos reduce la cantidad de código que necesita escribir cuando se admiten varias interfaces.

Las intersecciones son una característica opcional que no introducirá incompatibilidades con el código existente. El RFC se implementó en la tercera compilación alfa de PHP 8.1. Llegará el lanzamiento final a finales de noviembre después en este año.

Leave a Comment

You may also like

Más