Выходящий в Swift 5.9 package станет новым модификатором доступа в языке.
Команда Swift в Apple одобрила предложение по оценке Swift SE-0386, которое включает добавление нового модификатора доступа под названием package, позволяющего получать доступ к функциям только внутри одного модуля.
В настоящее время существует только один способ получить доступ к функциям во всех модулях проекта, и это путем объявления их как public. Однако иногда вы не хотите, чтобы доступ к определенной функции осуществлялся из другого модуля, а только внутри того же модуля. Прямо сейчас нет никакого способа ввести это ограничение.
К счастью, предложение по оценке Swift SE-0386 добавляет точное ограничение к языку, добавляя новый модификатор доступа package. Все, что вам нужно сделать, это объявить функцию как package.
Предположим, у нас есть два модуля под названием Cat и Dog. Если мы объявим общедоступную структуру под названием AnimalBehavior внутри модуля Cat, все его функции будут доступны в модуле Dog, а также в других по всему проекту:
// Module: Cat, Package: Cat
public struct AnimalBehaviour {
public func run() {}
public func actNaughty() {}
}
public struct Cat {
public let behaviour: AnimalBehaviour
}
let cat = Cat(behaviour: AnimalBehaviour())
cat.behaviour.run() // ✅ Accessible
cat.behaviour.actNaughty() // ✅ Accessible
// Module: Dog, Package: Dog
public struct Dog {
public let behaviour: AnimalBehaviour
}
let dog = Dog(behaviour: AnimalBehaviour())
dog.behaviour.run() // ✅ Accessible
dog.behaviour.actNaughty() // ✅ Accessible
Однако мы хотим, чтобы функция actNaughty() была доступна только внутри модуля, в котором мы объявили AnimalBehaviour, то есть Cat. Мы просто объявляем метод как package:
// Module: Cat, Package: Cat
public struct AnimalBehaviour {
public func run() {}
package func actNaughty() {}
}
Теперь можно получить доступ к actNaughty() внутри модуля Cat:
let cat = Cat(behaviour: AnimalBehaviour())
cat.behaviour.run() // ✅ Accessible
cat.behaviour.actNaughty() // ✅ Accessible
Однако для модуля Dog компилятор не сможет найти нужную функцию:
let dog = Dog(behaviour: AnimalBehaviour())
dog.behaviour.run() // ✅ Accessible
dog.behaviour.actNaughty() // ❌ Not accessible. Error: cannot find 'actNaughty()' in scope
Надеемся, что этот новый модификатор доступа поможет лучше структурировать крупные проекты.
В целом, этот модификатор доступа в значительной степени похож на internal, за исключением того, что он был создан для модулей, которые выражаются Swift Package Manager, чтобы предотвратить нежелательные функции, разрешая им совместное использование только внутри одного модуля.
Также стоит упомянуть, что package более доступен, чем internal, fileprivate и private. И менее доступный, чем open и public. Например, public функция не может использовать тип package в своих параметрах или тип возвращаемого значения, а функция package не может использовать внутренний тип в своих параметрах или тип возвращаемого значения. Аналогично, public функция @inlinable не может использовать объявление package в своей реализации, а функция @inlinable package не может использовать внутреннее объявление в своей реализации.
Swift 5.9 был анонсирован 6 марта 2023 года. Дата релиза пока не разглашается, но ожидается, что он выйдет вместе с запуском iOS 17.