2015-05-06 3 views
8

Я недавно читал Protocols, Generic Type Constraints and Arrays in Swift. Мой вопрос касается следующих двух примеров из блога:Поведение протоколов с самим собой

Код:

protocol MyProtocol1 { 
    var myValue: Self { get } 
} 

let array: [MyProtocol1] = [] // Error. 

Выдает ошибку:

Protocol 'MyProtocol1' can only be used as a generic constraint because it has Self or associated type requirements.

что ожидается и там было несколько С.О. вопросы, касающиеся этой темы. Однако, изменив myValue на функцию, больше не возникает никакой ошибки, но в обоих случаях возвращается Self.

protocol MyProtocol2 { 
    func myValue() -> Self 
} 

let array: [MyProtocol2] = [] // This is okay. 

Кто-нибудь знает причину этого, казалось бы, странного поведения?

+0

Я рекомендую обсудить это на devforums. Я подозреваю, что это угловой случай и не может быть преднамеренным. У разработчиков Swift гораздо больше шансов дать окончательный ответ. –

+0

Вы в итоге нашли ответ на это поведение? – bartzy

ответ

0

У меня нет окончательного ответа на это, но я чувствую, что это может быть связано с размером класса и внутренней планировкой.

Наличие связанного типа или члена типа Self будет влиять на размер объекта и, следовательно, размер массива, но использование типа возврата типа Self как метод влияет на размер объекта.

+0

Это интересная идея, но если бы это было так, вы бы ожидали, что бокс 'Self' исправит это. Например, если вы объявили «var myValue: Self? {get} '. Это поместило бы «Self» неизвестного размера внутри «Необязательно» известного размера и устранило проблему макета. (Этот метод используется для рекурсивных перечислений, например, которые имеют эту проблему размера.) Но это не помогает. –

2

Это объясняется около 18 минут в этом видео: https://developer.apple.com/videos/wwdc/2015/?id=408

Поскольку ваши ссылки протокола «самостоятельно» он может быть использован только в качестве общего ограничения не в качестве типа.

Пример: Скажем, 2 структуры реализуют ваш протокол - Duke & Серебро.

Если вы создали массив протокола2 ([protocol2]), то ваш массив может содержать либо герцогов, либо Silvers.

myValue конкретно указывает, что возвращаемое значение должно быть само. Это означает, что герцог должен вернуть герцога, а Серебро должно вернуть Серебро. Таким образом, вы не можете использовать Dukes & Silvers в том же массиве, потому что их функции MyValue имеют разные значения возврата.

Чтобы устранить эту проблему, вы можете:

1) Сделайте тип возврата MyValue протокола2 так, что герцоги и Silvers как раз возвращают тип протокола2

2) Сделать массив дженериков, которые соответствуют к протоколу2

+0

Вы упустили точку вопроса. Протокол с свойством типа 'Self' -' var myValue: Self {get set} '- будет иметь' Self или связанные требования типа 'и будет использоваться только как ограничение типа. Напротив, протокол с функцией, возвращающей значение типа 'Self' -' func myValue() -> Self', может использоваться как тип, а не только ограничение типа.Загадочный вопрос заключается в том, почему требование * свойства * к свойству type * Self' имеет другое поведение, чем требование * функции * протокола, которое возвращает значение типа 'Self'. –

+0

А, действительно. Я не полностью изучил этот вопрос. Спасибо. – JoeyBartez