# Access Control and Modules — Swift

Source: https://www.skillbyai.com/en/swift/m-access

> Use access levels to design clear module APIs.

## Who can see what

Swift's access control works at the level of **modules** (an app target, a framework or a Swift package target) and **source files**. From most to least restrictive: **`private`** (visible within the enclosing declaration and its extensions in the same file), **`fileprivate`** (the whole file), **`internal`** (the default: anywhere in the same module), **`package`** (Swift 5.9+: other modules in the same Swift package), **`public`** (visible to other modules, but classes cannot be subclassed and methods cannot be overridden outside the module) and **`open`** (public plus subclassing and overriding from other modules). **`private(set)`** and similar forms restrict only the setter. Good API design keeps most things `internal` or `private` and exposes a small, deliberate `public` surface from frameworks and packages. Unit tests can reach internal symbols with `@testable import`, so you do not need to make things public just for testing. Splitting an app into **local Swift packages** with clear public APIs improves build times and enforces boundaries between features.

## Access levels in a package

Only the public API is visible to other modules.

```swift
// Sources/Pricing/PriceCalculator.swift  (module: Pricing)
public struct PriceCalculator {
    public init(taxRate: Double = 0.18) { self.taxRate = taxRate }

    public func total(forPaise subtotal: Int) -> Int {
        subtotal + tax(on: subtotal)
    }

    let taxRate: Double                           // internal: invisible to other modules

    private func tax(on amount: Int) -> Int {      // private: only inside this type
        Int((Double(amount) * taxRate).rounded())
    }
}

open class PricingRule {                          // open: subclassable from other modules
    public init() {}
    open func adjust(_ paise: Int) -> Int { paise }
}

// App target
import Pricing
let calculator = PriceCalculator()
let payable = calculator.total(forPaise: 49_900)   // 58_882
// calculator.taxRate                           // error: internal to Pricing

// Tests
// @testable import Pricing   -> internal members become visible to tests
```

## Rooms in a house

private is your bedroom, fileprivate the flat, internal the whole building, package the housing society, public the front gate that visitors may use, and open a door you also allow visitors to remodel.

**Quiz:** What is the default access level in Swift?

- [ ] private
- [x] internal
- [ ] public
- [ ] open

*Answer:* internal. Declarations are internal by default: visible throughout their module.
