Swift 5.6 SE-0335 Introducir existencial any的理解

En la lista de actualizaciones de Swift 5.6, vi una breve introducción a existencial any , pero debido a que era demasiado simple, estaba confundido. Después de algunas verificaciones, aquí está mi comprensión de este cambio. SE-0335

Breve ejemplo

Normalmente cuando usamos un protocolo, es para asegurar la consistencia del tipo y cumplir con algunos requisitos, como implementar un método determinado:

protocol ProtocolA {
    func test()
}

struct Test: ProtocolA {
    func test() {
        print("hello")
    }
}

let t = Test()
t.test() /// Static Dispatch
复制代码

En este momento, el ttipo está claramente escrito y Swift usará Static Dispatcht.test() para la llamada , que es más eficiente.

Si queremos llamar al método porque no podemos especificar el tipo en algunos casos (lo que sucede) test, entonces escribiremos de esta manera:

let t: ProtocolA = Test()
t.test() /// Dynamic Dispatch
复制代码

El ttipo en este momento puede denominarse tipo existencial . Swift usará Dynamic Dispatch para completar la testllamada. La escena actual es una llamada de tabla en V , que es menos eficiente que el envío estático.

Por lo tanto , se agrega una nueva palabra clave en SE-0335 para tratar con el tipo existente.La escritura anterior debe estar en 5.6:any

let t: any ProtocolA = Test()
t.test() /// Static Dispatch
复制代码

En este punto, tendrá lugar el despacho estático.

Otro ejemplo

Tal vez pienses que este tipo de escena es rara, entonces daré dos ejemplos más.

Ejemplo 1

struct A {
    var obs: [ProtocolA]?
}

let a = A()
a.obs?.map {
    /// dynamic dispatch
    $0.test()
}

struct B {
    /// 引入any关键字
    var obs: [any ProtocolA]?
}

let b = B()
b.obs?.map {
    /// static dispatch
    $0.test()
}
复制代码

Se puede ver que en el desarrollo diario, el escenario anterior se encuentra a menudo. El método de escritura original obdistribuirá dinámicamente cada uno, pero después de la introducción de anypalabras clave, se convierte en una distribución estática, lo que mejora la eficiencia.

Ejemplo 2

El segundo escenario es la duda que encontré al escribir componentes básicos.Puedes mirar el código primero:

func test1(obj: ProtocolA) {
    obj.test()
}

func test2<T: ProtocolA>(obj: T) {
    obj.test() 
}
复制代码

Antes estaba muy confundido acerca de la diferencia entre los dos métodos de escritura, porque no hay diferencia en el nivel de compilación (el tipo se puede especificar cuando el método usa un tipo genérico como valor de retorno). Ahora, a través del análisis anterior, podemos entender que la test1llamada al método en el medio se envía dinámicamente, y test2la llamada al método en el método es envío estático. Obviamente, la última es una forma más científica de escribir, y luego la primera es más fácil. para entender cuándo lo usamos, por lo que las anypalabras clave son útiles:

func test(obj: any ProtocolA) {
    obj.test() /// Static Dispatch
}
复制代码

encima.

luego

Esta función está disponible actualmente en Xcode 13.3 . Para esta característica, según el plan de Apple, en la futura versión de Swift 5.x , se emitirá una advertencia donde esté involucrada y se arrojará un error directamente al comienzo de Swift 6 .

Este cambio tiene el potencial de romper el código existente en el futuro, por lo que se debe usar la forma correcta siempre que sea posible durante el período de transición. Personalmente, este cambio es muy importante y la comprensión de los tipos de Protocolo también se puede profundizar a través del proceso de comprensión.

Supongo que te gusta

Origin juejin.im/post/7078192732635676680
Recomendado
Clasificación