2015-05-27 5 views
1

Я пытаюсь создать протокол, который использует общий перечисление в swift. Компилятор выдает эту ошибку: Protocol can only be used as a generic constraint because it has associated type requirementsПротокол Swift, который использует перечисление с общим ассоциированным типом

Короткий код надрезается:

enum GenericEnum<T> { 
    case Unassociated 
    case Associated(T) 
} 

protocol AssociatedProtocol { 
    typealias AssociatedType 
    func foo() -> GenericEnum<AssociatedType> 
} 

let bar = [AssociatedProtocol]() 

Вы можете найти более длинный пример here.

Кто-нибудь знает решение этой проблемы?

+0

Что такое 'AssociatedType' псевдоним? – Grimxn

ответ

4

Возникла проблема: представьте себе некоторые последующие строки кода.

// none of this will compile... 
var bar = [AssociatedProtocol]() 
bar.append(GenericEnum.Associated(1)) 
bar.append(GenericEnum.Associated("hello") 
let foo = bar[0].foo() 

Какой тип foo? Это GenericEnum<Int> или GenericEnum<String>? Или нет?

Это особенно проблема, потому что перечисления, как и структуры, являются «типами значений». Это означает, что их размер определяется тем, что они содержат. Возьмите следующий код:

let x = GenericEnum.Associated(1) 
sizeofValue(x) // 9 - 1 byte for the enum, 8 for the Int 
let y = GenericEnum.Associated("hello") 
sizeofValue(y) // 25 - 1 byte for the enum, 24 for the String 

Протоколы со связанными типами действительно существуют только для ограничения общих функций. Так что это было бы хорошо:

func f<T: AssociatedProtocol>(values: [T]) { 
    var bar = [T]() // T is an instance of a specific 
        // AssociatedProtocol where T.AssociatedType 
        // is fixed to some specific type 
} 

, но использовать его автономно, не имеет смысла (по крайней мере с текущей версией 1.2 Swift - новые функции могут позволить другие вещи в версии).

Если вам нужен протокол, который будет использоваться в динамическом режиме во время выполнения, вам нужно будет оттолкнуть typealias. Затем вместо этого он может использоваться как ссылка фиксированного размера.

+0

Спасибо за это объяснение. Слишком плохо, что он не работает с Swift 1.2. – benrudhart

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