2016-11-09 4 views
2

Почему не работает следующий код? И что мне нужно изменить, чтобы заставить его работать?Swift 3 - Структуры в коллекции

//: 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 

Я понял, что если я создам структуру класса Swift, это сработает. Связано ли это с тем, что структура является типом значений? Я вижу ошибку компилятора в последней строке. «[Лицо]» не конвертируется в «<>» «

Спасибо.

ответ

3
extension Collection where Iterator.Element: Person 

ограничивает Iterator.Element к типам, которые принимают протоколPerson или являются подкласса из Person. И это не представляется возможным с struct Person, и в полном компиляторе журнала вы найдете

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

То, что вы, вероятно, имеете в виду

extension Collection where Iterator.Element == Person 

, которая ограничивает расширение к коллекциям Person. С другой стороны, определить протокол

protocol HasAge { 
    var age: Int { get } 
} 

принять что Person

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

и определить расширение для коллекций элементов, которые имеют возраст:

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

Благодарим вас за объяснение. Я не знал, что есть Итератор. Элемент == Человек даже возможен. –

+0

@ user3654258: Такое требование «такого же типа» возможно для 'Collection' (которое сам протокол), но в настоящее время не для' Array' (который является общей структурой). –

1

Изменение расширения вашей коллекции на это

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 
    } 
} 
Смежные вопросы