Access Control trong Swift
1. Giới thiệu
Access control giới hạn quyền truy cập vào code từ các phần khác của chương trình.
2. Các mức Access Control
| Mức | Phạm vi |
|---|---|
open | Mọi nơi + có thể override/kế thừa |
public | Mọi nơi trong các modules |
internal | Trong cùng module (mặc định) |
fileprivate | Trong cùng file |
private | Trong cùng scope (class/struct) |
3. Private
class BankAccount {
private var balance: Double = 0
private let accountNumber: String
init(accountNumber: String) {
self.accountNumber = accountNumber
}
func deposit(_ amount: Double) {
if amount > 0 {
balance += amount
}
}
func withdraw(_ amount: Double) -> Bool {
if amount > 0 && balance >= amount {
balance -= amount
return true
}
return false
}
func getBalance() -> Double {
balance
}
}
let account = BankAccount(accountNumber: "123456")
account.deposit(1000)
// account.balance = 0 // Error: 'balance' is private
print(account.getBalance()) // 1000.04. Fileprivate
// Trong cùng file, có thể truy cập
class DataManager {
fileprivate var cache: [String: Any] = [:]
fileprivate func clearCache() {
cache.removeAll()
}
}
class CacheHelper {
let manager = DataManager()
func reset() {
// OK: cùng file
manager.clearCache()
manager.cache = [:]
}
}5. Internal (Default)
// Không cần từ khóa - mặc định là internal
struct User {
var name: String // internal
var email: String // internal
func validate() { // internal
// ...
}
}
// Tường minh:
internal struct Product {
internal var price: Double
}6. Public và Open
// Trong framework/library
// Public: có thể truy cập nhưng không override
public class NetworkManager {
public var baseURL: String
public init(baseURL: String) {
self.baseURL = baseURL
}
public func fetch(endpoint: String) {
// ...
}
}
// Open: có thể override trong module khác
open class UIComponent {
open func render() {
print("Rendering...")
}
}7. Private Set
struct Counter {
// Đọc được từ ngoài, chỉ ghi được từ trong
private(set) var count: Int = 0
mutating func increment() {
count += 1
}
mutating func reset() {
count = 0
}
}
var counter = Counter()
print(counter.count) // 0 - OK
counter.increment()
print(counter.count) // 1 - OK
// counter.count = 100 // Error: setter is private8. Access Control cho Types
// Struct/Class
private struct InternalHelper { }
public class PublicService { }
// Enum
public enum APIError: Error {
case networkError
case invalidData
}
// Protocol
internal protocol DataSource {
func loadData()
}9. Computed Properties
class User {
private var _password: String = ""
public var password: String {
get { String(repeating: "*", count: _password.count) }
set { _password = hashPassword(newValue) }
}
private func hashPassword(_ p: String) -> String {
// Hashing logic
p + "_hashed"
}
}10. Best Practices
// ✅ Good: Encapsulation tốt
class ShoppingCart {
private var items: [CartItem] = []
var itemCount: Int { items.count }
var total: Double { items.reduce(0) { $0 + $1.price } }
func add(_ item: CartItem) {
items.append(item)
}
func remove(at index: Int) {
guard items.indices.contains(index) else { return }
items.remove(at: index)
}
}
// ❌ Bad: Expose implementation
class BadCart {
var items: [CartItem] = [] // Public - có thể modify trực tiếp
}11. Subclassing Access
public class Animal {
private var internalState: Int = 0
fileprivate var sharedState: Int = 0
public func publicMethod() { }
private func privateMethod() { }
}
// Trong cùng file
class Dog: Animal {
func test() {
// self.internalState // Error: private
self.sharedState = 1 // OK: fileprivate
publicMethod() // OK
// privateMethod() // Error: private
}
}📝 Tóm tắt
private- chỉ trong scope hiện tạifileprivate- trong cùng fileinternal- trong cùng module (mặc định)public- mọi nơi, không overrideopen- mọi nơi, có thể overrideprivate(set)- đọc public, ghi private
Last updated on
Swift