2015-10-19 10 views
5

Sto cercando di capire come funziona:Swift Tipo Optional: come funziona .None == nil

1> func returnNone() -> String? { return .None } 
    2> returnNone() == nil 
$R0: Bool = true 
    3> returnNone() == .None 
$R1: Bool = true 

Perché .None è uguale nil.

non vedo nulla nella definizione enum:

public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible { 
    case None 
    case Some(Wrapped) 
    /// Construct a `nil` instance. 
    public init() 
    /// Construct a non-`nil` instance that stores `some`. 
    public init(_ some: Wrapped) 
    /// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`. 
    @warn_unused_result 
    @rethrows public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U? 
    /// Returns `nil` if `self` is nil, `f(self!)` otherwise. 
    @warn_unused_result 
    @rethrows public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U? 
    /// Create an instance initialized with `nil`. 
    public init(nilLiteral:()) 
} 

risposta

12

enum Optional conforme al protocollo NilLiteralConvertible, che significa che può essere inizializzato con il "nullo" letterale. Il risultato è Optional<T>.None dove il tipo segnaposto T deve essere dedotto dal contesto.

Come esempio,

let n = nil // type of expression is ambiguous without more context 

non compila, ma

let n : Int? = nil 

fa, e il risultato è Optional<Int>.None.

Ora optional possono in generale, non sono paragonabili, se il sottostante tipo non è Equatable:

struct ABC { } 

let a1 : ABC? = ABC() 
let a2 : ABC? = ABC() 

if a1 == a2 { } // binary operator '==' cannot be applied to two 'ABC?' operands 

e anche questo non compila:

if a1 == Optional<ABC>.None { } // binary operator '==' cannot be applied to two 'ABC?' operands 

Ma questo compila:

if a1 == nil { } 

Utilizza l'operatore

public func ==<T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool 

dove _OptionalNilComparisonType non è documentato ufficialmente. In https://github.com/andelf/Defines-Swift/blob/master/Swift.swift la definizione può essere trovato come (trovato dai @rintaro e @Arsen, vedi commenti):

struct _OptionalNilComparisonType : NilLiteralConvertible { 
    init(nilLiteral:()) 
} 

Questo permette il confronto di qualsiasi tipo opzionale "zero", indipendentemente dal fatto che il tipo sottostante è Equatable oppure no.

In breve - nel contesto di Optional - nil può essere pensato come un collegamento a .None, ma il tipo di calcestruzzo deve essere dedotto dal contesto. C'è un operatore dedicato == per il confronto con "nil".

+0

@Cosyn: Se si definisce il proprio 'enum Op ' allora si dovrà anche definire l'operatore '==' per quel tipo. Ma hai ragione, l'ultima frase è stata fuorviante. –

+0

@MartinR @Cosyn e allora. La risposta è da qualche parte Apple definisce il metodo '==' per il confronto Tipi opzionali? – Arsen

+0

Bene, dopo aver aggiunto ==, allora funziona – Cosyn