В Swift существует пять уровней доступа к членам типов (свойства, методы, т.д.) и самим типам:
open — максимальная степень публичности. Можно наследовать и переопределять даже за пределами модуля.public — доступно вне модуля, но нельзя переопределять/наследовать.internal (по умолчанию) — доступно внутри модуля.fileprivate — доступно только в рамках файла.private — доступно только в пределах области объявления (extension тоже в этом scope).private для логики, которая не должна быть видна нигде вне объявления.fileprivate — если требуется обмен данными в одном файле (например, между двумя связанными extensions).internal — дефолт для всего общедоступного в модуле.public/open — для API, используемых другими модулями/фреймворками.open class MyOpenClass {} public class MyPublicClass {} internal class InternalClass {} fileprivate class FilePrivateClass {} private class PrivateClass {}
Чем open отличается от public при описании класса? Почему не все public классы доступны для наследования?
Ответ:
open помечает класс/метод доступным для переопределения и наследования за пределами своего модуля. public только открывает доступ к использованию, но не позволяет делать наследников вне модуля. С одной стороны, это защищает реализацию от нежелательных изменений, с другой — открывает только нужные точки расширения.
public class PublicClass {} open class OpenClass {} // В другом модуле: class InheritFromOpen: OpenClass {} // OK class InheritFromPublic: PublicClass {} // Ошибка!
История
В общей библиотеке класс был отмечен как public, и внешний проект попытался расширить его, переопределив методы. Проект не компилировался из-за ошибочного понимания разницы public и open — это стоило команде лишней недели доработки интерфейса.
История
Внутри одного файла попытались получить доступ к private-свойству из extension — но свойство было объявлено не как fileprivate, а как private. Это привело к компиляторной ошибке, которую заметили только на интеграционной сборке.
История
В приложении с несколькими фреймворками все типы помечались как internal (по умолчанию). Когда понадобилось использовать типы между модулями, интерфейс был не доступен — пришлось переписывать десятки объявлений на public, что заняло дополнительное время и тестирование.