В чем разница между open и public в Swift
Что проверяют
Знаете ли вы модель доступа Swift и понимаете ли, что разница между open и public проявляется только на границе модуля. Следом обычно спрашивают, почему наследование снаружи запрещено по умолчанию и что делает final.
Как отвечать
Модуль в Swift это таргет: фреймворк, пакет SPM, само приложение. Уровни доступа от широкого к узкому: open, public, package, internal (по умолчанию), fileprivate, private.
public: класс и его члены видны в других модулях, но наследоваться от класса и переопределять методы там нельзя. Внутри своего модуля такой класс наследуется спокойно, если он неfinal;open: то же плюс наследование иoverrideиз чужого модуля. Применяется только к классам и их членам: методам, свойствам, сабскриптам;final: запрещает наследование и переопределение везде, включая свой модуль.
Объясните, зачем такое разделение. Автор библиотеки явно решает, какие точки расширения он поддерживает. Каждый open метод становится частью контракта: если внутри класса поменять порядок вызовов, наследник у клиента может сломаться. Поэтому public безопаснее по умолчанию, а open оставляют для классов, спроектированных под наследование, вроде базовых контроллеров в UI-фреймворке. Компилятору это тоже выгодно: зная, что снаружи метод никто не переопределит, он может заменить динамический вызов прямым.
Уровень package появился в Swift 5.9: он открывает доступ модулям одного пакета, не выставляя API наружу.
Где спотыкаются
Говорят, что public класс нельзя наследовать вообще. Внутри модуля можно, запрет действует только снаружи.
Пишут open struct или open protocol. Это ошибка компиляции: наследование в этом смысле есть только у классов.
Помечают всё подряд open «на всякий случай». В приложении это бессмысленно, а в SDK превращается в обязательство поддерживать поведение, которое никто не собирался делать расширяемым.