Моя цель состоит в том, чтобы S обладал свойствами P и ему не нужно было повторно объявлять его в определении структуры.
Это невозможно, если вы пытаетесь это сделать. Протоколы требуют определенного поведения. Соответствующие типы должны обеспечивать такое поведение. Если вам требуется хранилище для реализации поведения, то соответствующий тип должен предоставить хранилище.
Хорошо, если вам не нужно хранилище, тогда расширение может просто возвращать значения, как у вас. Но вы не можете вернуть вычисленные значения, а также иметь хранилище. То, что вы пытаетесь сделать, невозможно. Ты думаешь о классах, а не о протоколах. (Если вам нужны классы, это нормально. Используйте классы. С ними все в порядке.)
Хороший способ подумать о том, почему это невозможно в Swift, - рассмотреть следующий случай. Предположим, ваш протокол P
существует в какой-то форме, которая достигает того, что вы хотите. Теперь в одном модуле мы определяем:
struct S {}
Эта структура не требует хранения. Любые вызовы S()
в этом модуле ничего не выделяют. (В качестве альтернативы присвойте S
некоторые свойства, и он выделит определенный объем памяти.)
Теперь в каком-то другом модуле расширьте S
, чтобы соответствовать P
:
extension S: P {}
Куда пойдет хранилище для h
? Экземпляры могут уже существовать в тот момент, когда это расширение даже загружено. Что делать, если существует несколько протоколов, которые требуют дополнительного хранилища, и все они подключены к S
Какими смещениями в структуре S
должны быть эти свойства? Порядок будет очень важен для скомпилированного кода. Это не невозможно решить (ObjC делает это, используя технику, называемую ассоциированными объектами), но это большое дополнение к языку, которое предотвращает ряд важных оптимизаций, а Swift так не делает.