protocol extension swift optional

extension - swift syntax



¿Por qué no opcional Cualquiera puede contener nulo? (3)

¿Cómo representa Swift los opcionales? Lo hace mediante la asignación de SomeType? a una implementación concreta de la enumeración Optional :

Int? => Optional<Int> String? => Optional<String>

Una declaración simplificada de Optional ve así:

enum Optional<T> { case none // nil case some(T) // non-nil }

Ahora, una variable de tipo Any puede mantener una enumeración (o cualquier otro tipo de valor, o incluso información de metatipo), por lo que debería ser capaz de contener una cadena nil , también conocida como String?.none , también llamada Optional<String>.none

A ver qué pasa, sin embargo. Primero lo primero, nil corresponde al caso .none enum para todos los tipos:

nil == Optional<String>.none // true nil == Optional<Int>.none // true [Double]?.none == nil // also true

Por lo tanto, en la práctica, debería poder asignar nil a una variable declarada como Any . Es el compilador que no te deja hacer esto.

Pero, ¿por qué el compilador no le permite asignar nil a una variable Any ? Es porque no puede inferir a qué tipo asignar el caso .none enum. Optional es una enumeración genérica, por lo que necesita algo para completar el parámetro genérico T , y nil es demasiado amplio.

Esto da un mensaje de error que apoya el párrafo anterior:

let nilAny: Any = nil // error: nil cannot initialize specified type ''Any'' (aka ''protocol<>'')

El siguiente código funciona, y es equivalente a asignar un nil :

let nilAny: Any = Optional<Int>.none

, como la variable Any anterior en realidad tiene un valor válido de la enumeración Optional .

Las asignaciones indirectas funcionan, ya que tras bambalinas nil se convierte en Optional<Type>.none .

var nilableBool: Bool? var nilBoolAsAny: Any = nilableBool // the compiler has all the needed type information from nilableBool

A diferencia de otros idiomas, en Swift nil corresponde a un valor concreto. Pero necesita un tipo con el que trabajar, para que el compilador sepa qué Optional<T>.none debe asignar. Podemos pensar que la palabra clave proporciona una sintaxis de azúcar.

En Swift puedo declarar una constante de tipo Any y poner una String en ella.

let any: Any = "hello world"

Bueno. Por otro lado, no puedo poner un valor nil en any porque no es opcional.

let any: Any = nil error: nil cannot initialize specified type ''Any'' (aka ''protocol<>'') let any: Any = nil ^

Perfecto. Pero ¿por qué el compilador me permite escribir el siguiente código?

let couldBeNil: String? = nil let any: Any = couldBeNil print(any) // nil

¿ Any sigue la regla Swift de que solo una var / let opcional se puede rellenar con nil ?

Probado con Xcode Playground 7.2 + Swift 2.1.1


De los documentos de Swift: " Any : el protocolo al que todos los tipos se ajustan implícitamente".

Es decir typealias Any = protocol<>

¿Entonces cuando declaras String? , podría pensar en eso como Optional<String> , donde Optional<T> se puede implementar como:

enum Optional<T> { case Some(T), None }

Y las enumeraciones son tipos, por lo que se ajustan al protocolo Any . Como se indica en los comentarios, nil no es un tipo (y, por lo tanto, no se ajusta a Any , es la ausencia de un valor (y en este caso, ningún valor no tiene ningún tipo).

Los opcionales se incorporan al lenguaje y no son enumeraciones regulares, pero aún así se mantienen en conformidad con Any mientras que un tipo sin tipo no.


Para cualquiera que busque una forma de comprobar si Any contiene nil :

Si el po value llamada le dirá que una variable Any contiene el valor nil la siguiente línea aún no funciona:

if value == nil { ... } // Returns false and generates a warning

Primero debe convertirlo en un valor no acumulable antes de verificarlo, por ejemplo, cuando Probablemente alguno contiene una Date :

if Optional<Date>.none == value as? Date { ... } // Returns true and no warning

nota: no lo probé, por lo que no tengo garantías, pero la línea anterior también podría pasar cuando se escribe:

if Optional<Any>.none == value as? Any { ... }