Что означает «Протокол… может использоваться только как общее ограничение, потому что он имеет требования типа Self или связанные с ним»?

124

Я пытаюсь создать словарь (на самом деле HashSet ) с ключом для настраиваемого протокола в Swift, но он дает мне ошибку в заголовке:

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

и я не могу понять это.

protocol Observing: Hashable { }

var observers = HashSet<Observing>()
devios1
источник
@jtbandes Это не дубликат. Я спрашиваю, что на самом деле означает сообщение об ошибке. Что такое «требование собственного или связанного типа»?
devios1

Ответы:

90

Протокол Observingнаследуется от протокола Hashable, который, в свою очередь, наследуется от протокола Equatable. Протокол Equatableимеет следующие требования:

func ==(lhs: Self, rhs: Self) -> Bool

И протокол, который находится Selfгде-то внутри, не может использоваться где-либо, кроме как в ограничении типа.

Вот похожий вопрос.

newacct
источник
7
... потому что компилятор должен гарантировать, что это один и тот же тип с обеих сторон, но протокол только гарантирует, что он соответствует контракту. Понимаю. Тем не менее, похоже, что это Equatableне обязательно должно подразумевать, Equatableпоскольку это не является строго необходимым для генерации хэш-кода.
devios1
4
Ой, не ждите, потому что Dictionaryнужно знать, действительно ли данный объект является правильным ключом, потому что два разных объекта могут генерировать один и тот же хэш-код. Хм, это немного сложно. Так что проблема здесь действительно в Equatable.
devios1
4
Посмотрите на 0:56 великолепную презентацию Алексис Галлахер под названием: Протоколы со связанными типами и как они стали такими
finneycanhelp
@finneycanhelp Спасибо за это 👍👍. Отличное видео!
devios1
11

Чтобы решить эту проблему, вы можете использовать дженерики. Рассмотрим этот пример:

class GenericClass<T: Observing> {
   var observers = HashSet<T>()
}
ph1lb4
источник