1.Khái niệm:

Subscript được sử dụng để truy cập thông tin của một collection, sequence và một list trong Classes, Structures và Enumerations. Đặc biệt những Subscript có thể lưu trữ và truy xuất các giá trị bằng index mà không sử dụng một method riêng biệt. Đây là một lối tắt rất hiệu quả và ngắn gọn trong lập trình.

 

Bạn có thể định nghĩa nhiều subscript cho một kiểu đơn giản, và nạp chồng những subscript thích hợp để lựa chọn dựa trên kiểu của giá trị chỉ số thông qua subscript.Subscripts không giới hạn một chiều duy nhât , bạn có thể định nghĩa subscripts với nhiều tham số đầu vào sao cho phù hợp với nhu cầu tuỳ chỉnh của bạn

2.Cú pháp:

Subscript cho phép bạn truy vấn các trường hợp của một kiểu bằng cách viết một hoặc nhiều giá trị trong dấu ngoặc vuông sau tên ví dụ. Cú pháp của nó cũng tương tự như cả hai cú pháp instance method  và computed property. Bạn  định nghĩa subscript với subscript keyword, chỉ định một hoặc nhiều tham số đầu vào và một kiểu trả về, cùng một cách như  instance methods. Không giống như  instance methods,subscript  có thể được read-write hay read-only. Hành vi này được truyền đạt bởi một getter và setter trong cùng một cách như đối với computed properties:

subscript(index: Int) -> Int {
    get {
        // return an appropriate subscript value here
    }
    set(newValue) {
        // perform a suitable setting action here
    }
}

Các kiểu của  newValue cũng trả về giá trị như subscript. Cũng  với computed properties, bạn có thể chọn không chỉ định tham số (newValue) của setter. Một tham số mặc định gọi newValue được cung cấp cho setter của bạn nếu bạn không cung cấp cho nó

Cũng với các thuộc tính read-only,  bạn có thể đơn giản hóa việc kê khai của một read-only subscript bằng cách loại bỏ các từ khóa get :

subscript(index: Int) -> Int {
    // return an appropriate subscript value here
}


Dưới đây là ví dụ về read-only subscript , trả về một gía trị khi nhân mutiplier với index chúng ta truyền vào

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// Prints "six times three is 18"

 

Trong ví dụ này,TimesTable được tạo ra để đại diện cho three-times-table. , thông qua một giá trị từ 3 đến giá trị khởi tạo của structure sử dụng cho tham số multiplier của ví dụ.

Bạn có thể truy vấn các trường hợp threeTimesTable bằng cách gọi subscript của nó, như  gọi tới threeTimesTable[6]. Yêu cầu mục thứ sáu trong three-times-table, trong đó trả về một giá trị 18, hoặc 3 lần 6.        

  • NOTE
  • Một n-times-table được dựa trên một quy tắc toán học cố định. Nó không thích hợp để thiết lập threeTimesTable [someIndex] đến một giá trị mới, và do đó subscript cho TimesTable được định nghĩa là một subscript read-only.

 

3.Cách sử dụng:
Nghĩa chính xác của subscript phụ thuộc vào nội dung nơi mà nó được sử dụng. Về cơ bản, subscript được sử dụng để truy xuất các thành viên trong một tập hợp, danh sách hoặc một trình tự. Bạn tự do thực hiện subscript một cách phù hợp nhất cho tính năng của class hoặc struct cụ thể của bạn.
Ví dụ:
Kiểu Dictionary của Swift, thực thi một subscript để thiết lập và truy xuất giá trị lưu trữ bên trong một thể hiện của Dictionary. Bạn có thể truy xuất giá trị của dictionary bằng việc cung cấp key của  dictionary's key và gán giá trị cho một subscript.

var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
numberOfLegs["bird"] = 2

Ví dụ trên định nghĩa một biến có tên numberOfLegs và khởi tạo nó bằng một dictionary có chứa ba cặp key-value.Kiểu dictionary của numberOfLegs là [String: Int].Sau khi tạo dictionary ,ví dụ này sử dụng subcript để gán thêm một String key "bỉrd" và giá trị Int vào dictionary

 

4.Subscript option:
Subscript có thể lấy bất kỳ số lượng tham số đầu vào và những tham số đầu vào này có thể là bất kỳ kiểu dữ liệu nào. Subscript cũng có thể trả về bất kỳ kiểu dữ liệu nào. Subscript có thể sử dụng variable parameters và variadic parameters, nhưng không thể sử dụng in-out parameters hoặc cung cấp giá trị mặc định cho tham số.
Một class hoặc struct có thể cung cấp nhiều subscript để thực thi khi nó cần. Và những subscript thích hợp được sử dụng sẽ suy luận dựa trên kiểu của giá trị hoặc giá trị được chứa trong giỏ subscript tại điểm mà subscript sử dụng. Định nghĩa này của nhiều subscript được biết như là nạp chồng subscript.
Trong khi phổ biến nhất cho một subscript để lấy một tham số đơn, bạn cũng có thể định nghĩa một subscript với nhiều tham số nếu nó thích hợp cho kiểu của bạn. Theo ví dụ bên dưới định nghĩa một cấu trúc Matrix, đại diện cho ma trận 2 chiều cho kiểu giá trị Double. Subscript của cấu trúc Matrix có 2 tham số kiểu int như sau:

struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

 

Matrix cung cấp một trình khởi tạo để lấy 2 tham số row và col và tạo một array đủ lớn để lưu trữ giá trị row * col kiểu Double. Mỗi vị trí trong Matrix được cho giá trị khởi tạo là 0.0. Để đạt được điều này thì kích thước của mảng và giá trị ô khởi tạo của 0.0 được thông qua bởi một trình khởi tạo mảng, để tạo và khởi tạo một mảng mới với kích thước chính xác.

Bạn có thể xây dựng một Matrix mới bằng cách chuyển số hàng và số cột thích hợp giá trị khởi tạo của nó :

var matrix = Matrix(rows: 2, columns: 2)

Ví dụ trên tạo một Matrix mới với hai hàng và hai cột .Các mảng lưới của ma trận này có hiệu quả là một phiên bản phẳng của ma trận ,như đọc từ trên trái xuống dưới phải

../_images/subscriptMatrix01_2x.png

Giá trị trong ma trận có thể được đặt bằng cách đi qua các giá trị hàng và cột vào subscript, được tách bằng dấu phẩy

  1. matrix[0, 1] = 1.5
  2. matrix[1, 0] = 3.2

 

Hai câu lệnh gọi setter của subscript để đặt giá trị là 1.5 ở vị trí phía trên bên phải của ma trận (trong đó hàng là 0 và cột là 1 ) và 3.2 ở vị trí phía dưới bên trái (trong đó hàng là 1 và cột là 0)

 

../_images/subscriptMatrix02_2x.png

Getter và setter của Matrix cả hai đều chứa sự xác nhận để kiểm tra xem giá trị của hàng và cột của subscript có hợp lệ hay không .Để hỗ trợ sự xác nhận đó ,Matrix bao gồm một phương thức được gọi là indexIsValid(row:column:) để kiểm tra các hàng và cột được yêu cầu bên trong giới hạn của ma trận

func indexIsValid(row: Int, column: Int) -> Bool {
    return row >= 0 && row < rows && column >= 0 && column < columns
}

Một sự xác nhận được kích hoạt nếu bạn cố gắng truy cập một subscript nằm ngoài giới hạn ma trận 

let someValue = matrix[2, 2]
// this triggers an assert, because [2, 2] is outside of the matrix bounds