2016-11-09 2 views
2

Warum funktioniert der folgende Code nicht? Und was muss ich ändern, damit es funktioniert?Swift 3 - Strukturen in einer Sammlung

//: Playground - noun: a place where people can play 

import Cocoa 

struct Person: CustomDebugStringConvertible, Hashable { 
    let name: String 
    let age: Int 

    // MARK: CustomDebugStringConvertible 

    var debugDescription: String { 
     return "\(name) is \(age) years old" 
    } 

    // MARK: Hashable 

    var hashValue: Int { 
     return name.hashValue^age.hashValue 
    } 
} 

func ==(lhs: Person, rhs: Person) -> Bool { 
    return lhs.name == rhs.name && lhs.age == rhs.age 
} 

let ilse = Person(name: "Ilse", age: 33) 
let mark = Person(name: "Mark", age: 38) 

extension Collection where Iterator.Element: Person { 
    var averageAge: Int { 
     let sum = self.reduce(0) { $0 + $1.age } 
     let count = self.count as! Int 
     return sum/count 
    } 
} 

var people = [Person]() 
people.append(ilse) 
people.append(mark) 

let averageAge = people.averageAge 

Ich fand heraus, dass, wenn ich die Struktur eine Swift-Klasse machen es funktioniert. Hat es etwas damit zu tun, dass die Struktur ein Werttyp ist? Ich sehe einen Compilerfehler in der letzten Zeile. "'[Person]' ist nicht umwandelbar in '<>'"

Vielen Dank.

Antwort

3
extension Collection where Iterator.Element: Person 

schränkt Iterator.Element auf Typen, die nehmen das ProtokollPerson oder sind eine Unterklasse von Person. Beides ist nicht möglich, mit struct Person und im vollständigen Compiler einloggen Registrieren Sie

error: type 'Iterator.Element' constrained to non-protocol type 'Person'

Was Sie wahrscheinlich

bedeuten zu finden ist
extension Collection where Iterator.Element == Person 

, die die Erweiterung auf Sammlungen von Person einschränkt. Alternativ definieren ein Protokoll

protocol HasAge { 
    var age: Int { get } 
} 

dass Person

struct Person: CustomDebugStringConvertible, Hashable, HasAge { ... } 

durch nehmen und die Erweiterung für Sammlungen von Elementen definieren, die ein Alter haben:

extension Collection where Iterator.Element: HasAge { ... } 
+0

Vielen Dank für die Erklärung. Ich wusste nicht, dass es Iterator.Element == Person sogar möglich war. –

+0

@ user3654258: Eine solche "same-type" -Anforderung ist möglich für 'Collection' (die selbst ein Protokoll ist), aber derzeit nicht für' Array' (was eine generische Struktur ist). –

1

Ihre Erweiterung Sammlung Ändern Sie dies in

extension Collection where Iterator.Element == Person { 
    var averageAge: Int { 
     let sum = self.reduce(0) { $0 + $1.age } 
     let count = self.count as! Int 
     return sum/count 
    } 
}