Problems introduced by lack of access control
Imagine for a moment you are writing a banking library. This library would help serve as the foundation for your customers (other banks) to write their banking software.
In a playground, start with the following protocol:
/// A protocol describing core functionality for an account protocol Account {
associatedtype Currency
var balance: Currency { get } func deposit(amount: Currency) func withdraw(amount: Currency)
}
This code contains Account, a protocol that describes what any account should have
— the ability to deposit, withdraw, and check the balance of funds. Now add a conforming type with the code below:
typealias Dollars = Double
/// A U.S. Dollar based "basic" account. class BasicAccount: Account {
var balance: Dollars = 0.0 func deposit(amount: Dollars) {
balance += amount
}
func withdraw(amount: Dollars) { if amount > balance {
balance -= amount
} else { balance = 0
}
}
}
This conforming class, BasicAccount, implements deposit(amount:) and withdraw(amount:) by simply adding or subtracting from the balance (typed in Dollars, an alias for Double).
Although this code is very straightforward, you may notice a slight issue. The balance property in the Account protocol is designed to be read-only — in other words, it only has a get defined. However, the implementation of BasicAccount requires balance to be declared as a variable so that the value can be updated when funds are deposited or withdrawn.
This means nothing is stopping consuming code from directly assigning new values for balance:
// Create a new account
let account = BasicAccount()
// Deposit and withdraw some money account.deposit(amount: 10.00)
account.withdraw(amount: 5.00)
// ... or do evil things! account.balance = 1000000.00
Oh no! Even though you carefully designed the Account protocol to only be able to deposit or withdraw funds, the implementation details of BasicAccount that allow it to update its own balance could be used by any code.
Fortunately, you can use access control to limit the scope at which your code is visible to other types, files, or even software modules!
Note: Access control is not a security feature that protects your code from malicious hackers. Rather, it lets you express intent by generating helpful compiler errors if a user attempts directly access implementation details that may compromise the invariant.