Từ các tài liệu
Kiểm tra an toàn 1
Một trình khởi tạo được chỉ định phải đảm bảo rằng tất cả các thuộc tính được giới thiệu bởi lớp của nó được khởi tạo trước khi nó ủy quyền cho một trình khởi tạo siêu lớp.
Tại sao chúng ta cần kiểm tra an toàn như thế này?
Để trả lời điều này hãy đi qua mặc dù quá trình khởi tạo nhanh chóng.
Khởi tạo hai pha
Khởi tạo lớp trong Swift là một quá trình hai giai đoạn. Trong pha đầu tiên, mỗi thuộc tính được lưu trữ được gán một giá trị ban đầu bởi lớp đã giới thiệu nó. Khi trạng thái ban đầu cho mọi thuộc tính được lưu trữ đã được xác định, giai đoạn thứ hai bắt đầu và mỗi lớp sẽ có cơ hội tùy chỉnh các thuộc tính được lưu trữ của nó trước khi thể hiện mới được coi là sẵn sàng để sử dụng.
Việc sử dụng quy trình khởi tạo hai pha giúp khởi tạo an toàn, trong khi vẫn mang lại sự linh hoạt hoàn toàn cho mỗi lớp trong hệ thống phân cấp lớp. Khởi tạo hai pha ngăn không cho các giá trị thuộc tính được truy cập trước khi chúng được khởi tạo và ngăn các giá trị thuộc tính được đặt thành giá trị khác bởi một trình khởi tạo khác bất ngờ.
Vì vậy, để đảm bảo quá trình khởi tạo hai bước được thực hiện như được xác định ở trên, có bốn kiểm tra an toàn, một trong số đó là,
Kiểm tra an toàn 1
Một trình khởi tạo được chỉ định phải đảm bảo rằng tất cả các thuộc tính được giới thiệu bởi lớp của nó được khởi tạo trước khi nó ủy quyền cho một trình khởi tạo siêu lớp.
Bây giờ, khởi tạo hai pha không bao giờ nói về thứ tự, nhưng kiểm tra an toàn này, giới thiệu super.init
sẽ được đặt hàng, sau khi khởi tạo tất cả các thuộc tính.
Kiểm tra an toàn 1 có vẻ không liên quan vì,
Khởi tạo hai pha ngăn các giá trị thuộc tính không được truy cập trước khi chúng được khởi tạo có thể được thỏa mãn, mà không cần kiểm tra an toàn 1 này.
Giống như trong mẫu này
class Shape {
var name: String
var sides : Int
init(sides:Int, named: String) {
self.sides = sides
self.name = named
}
}
class Triangle: Shape {
var hypotenuse: Int
init(hypotenuse:Int) {
super.init(sides: 3, named: "Triangle")
self.hypotenuse = hypotenuse
}
}
Triangle.init
đã khởi tạo, mọi tài sản trước khi được sử dụng. Vì vậy, kiểm tra an toàn 1 dường như không liên quan,
Nhưng sau đó có thể có một kịch bản khác, một chút phức tạp,
class Shape {
var name: String
var sides : Int
init(sides:Int, named: String) {
self.sides = sides
self.name = named
printShapeDescription()
}
func printShapeDescription() {
print("Shape Name :\(self.name)")
print("Sides :\(self.sides)")
}
}
class Triangle: Shape {
var hypotenuse: Int
init(hypotenuse:Int) {
self.hypotenuse = hypotenuse
super.init(sides: 3, named: "Triangle")
}
override func printShapeDescription() {
super.printShapeDescription()
print("Hypotenuse :\(self.hypotenuse)")
}
}
let triangle = Triangle(hypotenuse: 12)
Đầu ra:
Shape Name :Triangle
Sides :3
Hypotenuse :12
Ở đây nếu chúng ta đã gọi super.init
trước khi cài đặt hypotenuse
, thì super.init
cuộc gọi sẽ gọi printShapeDescription()
và vì nó đã bị ghi đè, trước tiên nó sẽ dự phòng cho việc thực hiện lớp Tam giác printShapeDescription()
. Lớp printShapeDescription()
Tam giác truy cập vào hypotenuse
một thuộc tính không tùy chọn vẫn chưa được khởi tạo. Và điều này không được phép vì khởi tạo hai pha ngăn giá trị thuộc tính được truy cập trước khi chúng được khởi tạo
Vì vậy, hãy đảm bảo việc khởi tạo Hai pha được thực hiện như được xác định, cần phải có một thứ tự gọi cụ thể super.init
và sau khi khởi tạo tất cả các thuộc tính được giới thiệu bởi self
lớp, do đó chúng ta cần Kiểm tra an toàn 1