Skip to Content

Subscripts trong Swift

1. Giới thiệu

Subscripts cho phép truy cập elements bằng cú pháp [index].

2. Subscript cơ bản

struct Matrix { let rows: Int let columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, col: Int) -> Double { get { grid[row * columns + col] } set { grid[row * columns + col] = newValue } } } var matrix = Matrix(rows: 3, columns: 3) matrix[0, 0] = 1.0 matrix[1, 1] = 2.0 matrix[2, 2] = 3.0 print(matrix[1, 1]) // 2.0

3. Read-Only Subscript

struct TimesTable { let multiplier: Int subscript(index: Int) -> Int { multiplier * index } } let threeTimesTable = TimesTable(multiplier: 3) print(threeTimesTable[6]) // 18 print(threeTimesTable[9]) // 27

4. String Extension

extension String { subscript(index: Int) -> Character? { guard index >= 0, index < count else { return nil } return self[self.index(startIndex, offsetBy: index)] } subscript(range: Range<Int>) -> Substring? { guard range.lowerBound >= 0, range.upperBound <= count else { return nil } let start = index(startIndex, offsetBy: range.lowerBound) let end = index(startIndex, offsetBy: range.upperBound) return self[start..<end] } } let str = "Hello" print(str[0]) // Optional("H") print(str[4]) // Optional("o") print(str[1..<4]) // Optional("ell")

5. Multiple Parameters

struct Spreadsheet { private var cells: [[String]] init(rows: Int, cols: Int) { cells = Array(repeating: Array(repeating: "", count: cols), count: rows) } // Subscript với row, col subscript(row: Int, col: Int) -> String { get { cells[row][col] } set { cells[row][col] = newValue } } // Subscript với tên cell như A1, B2 subscript(cell: String) -> String { get { let col = Int(cell.first!.asciiValue! - 65) // A=0, B=1 let row = Int(String(cell.dropFirst()))! - 1 return cells[row][col] } set { let col = Int(cell.first!.asciiValue! - 65) let row = Int(String(cell.dropFirst()))! - 1 cells[row][col] = newValue } } } var sheet = Spreadsheet(rows: 10, cols: 5) sheet[0, 0] = "Name" sheet["B1"] = "Age" print(sheet["A1"]) // Name

6. Subscript trong Class

class DataStore { private var storage: [String: Any] = [:] subscript(key: String) -> Any? { get { storage[key] } set { storage[key] = newValue } } // Generic subscript subscript<T>(key: String, default defaultValue: T) -> T { storage[key] as? T ?? defaultValue } } let store = DataStore() store["name"] = "John" store["age"] = 30 print(store["name"]) // Optional("John") print(store["city", default: "Unknown"]) // Unknown

7. Static Subscripts

enum Settings { static var values: [String: String] = [:] static subscript(key: String) -> String? { get { values[key] } set { values[key] = newValue } } } Settings["theme"] = "dark" Settings["language"] = "en" print(Settings["theme"]) // Optional("dark")

8. Subscript Overloading

struct MultiArray { private var data: [Int] = Array(1...100) // Subscript bằng index subscript(index: Int) -> Int { data[index] } // Subscript bằng range subscript(range: Range<Int>) -> [Int] { Array(data[range]) } // Subscript bằng nhiều indices subscript(indices: Int...) -> [Int] { indices.map { data[$0] } } } let arr = MultiArray() print(arr[5]) // 6 print(arr[0..<5]) // [1, 2, 3, 4, 5] print(arr[0, 5, 10]) // [1, 6, 11]

9. Ví dụ thực tế: JSON-like Access

struct JSONValue { private var storage: Any init(_ value: Any) { self.storage = value } subscript(key: String) -> JSONValue? { guard let dict = storage as? [String: Any], let value = dict[key] else { return nil } return JSONValue(value) } subscript(index: Int) -> JSONValue? { guard let array = storage as? [Any], index < array.count else { return nil } return JSONValue(array[index]) } var stringValue: String? { storage as? String } var intValue: Int? { storage as? Int } } let json = JSONValue([ "name": "John", "age": 30, "friends": ["Alice", "Bob"] ]) print(json["name"]?.stringValue) // Optional("John") print(json["age"]?.intValue) // Optional(30) print(json["friends"]?[0]?.stringValue) // Optional("Alice")

📝 Tóm tắt

  • Subscript cho phép truy cập bằng []
  • Có thể có getset
  • Có thể nhận nhiều parameters
  • Có thể overload với các types khác nhau
  • static subscript cho type-level access
  • Hữu ích cho collections, matrices, JSON
Last updated on