2016-04-23 4 views
2

Я очень долго боролся с быстрыми протоколами и связанными типами. Я начал снова с базового, чтобы действительно понять, что происходит не так, и я последовал за этим article TypeErasure в Swift Protocols с требованием связанного типа Rob Napier, но все же мне не повезло.Быстрые протоколы с требованием связанного типа и реализация по умолчанию

Найти код ниже

// An Animal can eat 
protocol Animal { 
    associatedtype Food 
    func feed(food: Food) -> Void 
} 

struct AnyAnimal<Food>: Animal { 
    private let _feed: (Food) -> Void 
    init<Base: Animal where Food == Base.Food>(_ base: Base) { 
     _feed = base.feed 
    } 
    func feed(food: Food) { _feed(food) } 
} 

// Kinds of Food 
struct Grass {} 

struct Cow: Animal { 
    func feed(food: Grass) { print("moo") } 
} 

struct Goat: Animal { 
    func feed(food: Grass) { print("bah") } 
} 

let grassEaters = [AnyAnimal(Cow()), AnyAnimal(Goat())] 
for animal in grassEaters { 
    animal.feed(Grass()) 
} 

Теперь я хотел бы дать реализацию по умолчанию в животных протокола, как показано ниже

extension Animal { 

    func feed(food: Food) -> Void { 
     print("unknown") 
    } 
} 

И когда я извлекал функцию от структуры коровы я получаю сообщение об ошибке сообщение о том, что Корова не соответствует протоколу Animal.

Означает ли это, что у вас не может быть стираний типа и реализации по умолчанию вместе ?. Есть ли способ, которым я могу сделать TypeErasure, а также сохранить реализацию по умолчанию?

ответ

5

Проблема не связана с типом стирания, и вы получите то же сообщение об ошибке , если вы удалите определение struct AnyAnimal<Food>.

Если удалить метод feed() из struct Cow затем компилятор не может вывести соответствующий тип Food. Так как вы использовать конкретный тип в реализации по умолчанию:

extension Animal { 
    func feed(food: Grass) -> Void { 
     print("unknown") 
    } 
} 

struct Cow: Animal { 
} 

или определить тип псевдонима Food для каждого типа, используя реализацию по по умолчанию:

extension Animal { 
    func feed(food: Food) -> Void { 
     print("unknown") 
    } 
} 

struct Cow: Animal { 
    typealias Food = Grass 
} 

Также можно определить тип по умолчанию для Food в протоколе :

protocol Animal { 
    associatedtype Food = Grass 
    func feed(food: Food) -> Void 
} 


extension Animal { 
    func feed(food: Food) -> Void { 
     print("unknown") 
    } 
} 

struct Cow: Animal { 
} 
+0

Мой плохо, я не понял, это был такой глупый вопрос. Спасибо! –

Смежные вопросы