Что гарантирует требование базового класса в объявлении протокола?
Требование базового класса означает, что протокол могут реализовать только экземпляры этого класса или его подклассов. В generic-коде ограничение таким протоколом даёт доступ не только к требованиям протокола, но и к открытым членам указанного базового класса.
Это сильнее, чем ограничение AnyObject: AnyObject требует лишь ссылочный тип, но не связывает соответствие с конкретной иерархией классов.
Протоколы нужны для описания общего поведения, не привязанного к конкретной реализации. Однако иногда контракт имеет смысл только для объектов определённой иерархии: например, для контроллеров, представлений или сущностей, унаследованных от базового класса.
Требование базового класса позволяет выразить эту связь непосредственно в протоколе. Благодаря этому её не приходится повторять в каждом generic-ограничении или проверять вручную во время выполнения.
Одного требования AnyObject недостаточно, если протокол использует API конкретного базового класса. Любой класс может удовлетворить AnyObject, но это не означает наличие нужных свойств, методов или гарантий наследования.
Если оставить связь с базовым классом только в отдельных generic-функциях, часть кода может случайно принять неподходящий класс. Если же использовать протокол без такого ограничения, сам контракт не будет отражать реальную область применимости.
Базовый класс, указанный в наследовании протокола, становится superclass requirement. Соответствие допустимо только для класса, который является этим базовым классом или его подклассом; структуры и перечисления соответствовать такому протоколу не могут.
В inspect параметр T гарантированно является наследником Document, поэтому обращение к identifier корректно даже при отсутствии этого свойства в требованиях протокола. Одновременно доступны требования ArchivableDocument.
Это отличается от протокольной композиции вроде Document & ArchivableDocument. Композиция задаёт ограничение в конкретном месте использования, а superclass requirement делает связь частью самого протокола и позволяет писать generic-код с одним ограничением T: ArchivableDocument.
По сравнению с AnyObject ограничение базовым классом уменьшает множество допустимых типов, зато усиливает статические гарантии. По сравнению с обычным протоколом оно уменьшает повторное использование: типы из другой иерархии уже не смогут соответствовать этому контракту, даже если имеют совместимый набор методов.
В модуле архивирования требуется принимать только документы приложения, потому что обработчик использует их идентификатор и жизненный цикл. Рассматривались три варианта.
Первый вариант — ограничить протокол только AnyObject. Он допускает больше типов, но не позволяет безопасно обращаться к API Document; дополнительные приведения типов сделали бы код хрупким.
Второй вариант — оставить обычный протокол и писать Document & ArchivableDocument во всех generic-функциях. Это технически работает, но дублирует правило и позволяет использовать протокол без обязательного контекста базового класса.
Третий вариант — объявить superclass requirement. Он выбран, потому что правило относится к самой семантике протокола: архивируемым считается только Document или его подкласс. В результате generic-код получает статическую проверку наследования и прямой доступ к API базового класса.
Нет. Структура не может наследоваться от класса, поэтому компилятор отвергнет такое соответствие. Наличие методов с подходящими сигнатурами не компенсирует отсутствие требуемой классовой иерархии.
AnyObject?AnyObject ограничивает протокол ссылочными типами, но разрешает соответствие любому классу. Требование базового класса дополнительно фиксирует конкретную иерархию и даёт generic-коду гарантированный доступ к членам этого класса.
Да, но его existential-значение сможет содержать только экземпляр указанного базового класса или его подкласса. При работе через any ArchivableDocument сохраняется гарантия классовой природы и базового класса, однако конкретный тип подкласса стирается; операции, требующие знания именно этого подкласса, становятся недоступны без дополнительного приведения.