2016-12-30 2 views
4

ich nicht den Zweck/Bedeutung von "Indices.Iterator.Element == Index" in folgendem Code, was die Bedeutung der "Collection wo Indices.Iterator.Element == Index" ist

extension Collection where Indices.Iterator.Element == Index { 

    /// Returns the element at the specified index iff it is within bounds, otherwise nil. 
    subscript (safe index: Index) -> Generator.Element? { 
     return indices.contains(index) ? self[index] : nil 
    } 
} 
+0

Beachten Sie, dass ich [meine Antwort hier] (http://stackoverflow.com/a/40331858/2976878) aktualisiert habe, was (hoffentlich) die Gründe für die Einschränkung besser erklärt. – Hamish

Antwort

6

Die herausfinden konnte, Generische Constraint-Syntax where T == U besagt, dass der Typ T vom selben Typ wie der Typ U sein muss.

Lassen Sie uns zunächst ein einfacheres Beispiel tun:

protocol GenericProtocol { 
    associatedtype T 
    associatedtype U 
} 

extension GenericProtocol where T == U { 
    func foo() {} 
} 

class ConcreteClassA: GenericProtocol { 
    typealias T = Int 
    typealias U = Float 
} 

class ConcreteClassB: GenericProtocol { 
    typealias T = Int 
    typealias U = Int 
} 

let a = ConcreteClassA() 
let b = ConcreteClassB() 

Jetzt von diesen, die a oder b das Mitglied hat foo? Die Antwort ist b.

Da die generische Einschränkung der Erweiterung sagt, dass T und U vom gleichen Typ sein muss, wird die Verlängerung nur auf ConcreteClassB angewendet, da seine T und U beide Int sind.

Zurück zu Ihrem Code jetzt.

In Ihrem Code, Sie sagen, dass Indices.Iterator.Element muss der gleiche Typ wie Index sein. Stellen wir uns vor, was diese beiden Typen sind.

Indices ist die Art der Eigenschaft indices. So ist Indices.Iterator.Element der Typ jedes Index der Sammlung. Index Auf der anderen Seite ist der Typ des Werts, den Sie in den Index der Sammlung einfügen können. Diese Einschränkung erscheint übertrieben, ist es aber in Wirklichkeit nicht. Ich kann mir kein Beispiel für einen Typ vorstellen, bei dem die Einschränkung nicht zutrifft. Aber Sie können theoretisch einen solchen Typ erstellen. Deshalb ist die Einschränkung da.

Wenn die Einschränkung nicht da wäre, würde dies nicht kompilieren:

indices.contains(index) 
+0

Vielen Dank, es erklärt sehr, sehr klar :) – Jacky

+0

Wenn Sie denken, dass meine Antwort Ihre Frage beantwortet, denken Sie bitte darüber nach, es zu akzeptieren! @Jacky – Sweeper

+0

Xcode 9 sagt, das ist redundant. (mit einer Warnung): ** Redundante gleichartige Bedingung 'Self.Index' == 'Self.Indices.Iterator.Element' ** – Jonny

1

contains(_:) auf der indices Eigenschaft aufgerufen wird (die Indices hat Typ), mit dem Parameter index genannt (welcher Typ Index hat) . Dies ist nur möglich, wenn die Elemente Indices vom selben Typ sind wie Index.

Diese Einschränkung wird hinzugefügt, um zu bestätigen, dass dies wahr ist, wodurch der Code kompiliert werden kann.

Beispiel Array nehmen. Sein zugehöriger Typ Indices ist auf CountableRange<Int> eingestellt, und sein zugehöriger Typ Index ist auf Int eingestellt. Array ist in der Lage, Ihrem Protokoll zu entsprechen, da die Elemente des Iterators CountableRange<Int>() und der Typ Index beide Int sind.

Verwandte Themen