จากเอกสาร
ตรวจสอบความปลอดภัย 1
ตัวกำหนดค่าเริ่มต้นที่กำหนดต้องตรวจสอบให้แน่ใจว่าคุณสมบัติทั้งหมดที่แนะนำโดยคลาสนั้นถูกเตรียมใช้งานก่อนที่จะมอบสิทธิ์ให้กับตัวเริ่มต้น superclass
ทำไมเราต้องตรวจสอบความปลอดภัยเช่นนี้
เพื่อตอบคำถามนี้ให้ดำเนินการต่อแม้ว่ากระบวนการเตรียมใช้งานจะดำเนินไปอย่างรวดเร็ว
การเริ่มต้นสองเฟส
การเริ่มต้นคลาสใน Swift เป็นกระบวนการสองเฟส ในเฟสแรกแต่ละคุณสมบัติที่เก็บไว้จะถูกกำหนดเป็นค่าเริ่มต้นโดยชั้นเรียนที่นำมาใช้ เมื่อสถานะเริ่มต้นสำหรับคุณสมบัติที่เก็บไว้ทั้งหมดถูกกำหนดระยะที่สองจะเริ่มต้นขึ้นและแต่ละชั้นจะได้รับโอกาสในการปรับแต่งคุณสมบัติที่จัดเก็บเพิ่มเติมก่อนที่อินสแตนซ์ใหม่จะได้รับการพิจารณาว่าพร้อมใช้งาน
การใช้กระบวนการกำหนดค่าเริ่มต้นแบบสองเฟสทำให้การกำหนดค่าเริ่มต้นปลอดภัยในขณะที่ยังให้ความยืดหยุ่นอย่างสมบูรณ์กับแต่ละคลาสในลำดับชั้นของคลาส การกำหนดค่าเริ่มต้นแบบสองเฟสป้องกันค่าคุณสมบัติจากการเข้าถึงก่อนที่จะเริ่มต้นและป้องกันไม่ให้ค่าคุณสมบัติถูกตั้งค่าเป็นค่าที่แตกต่างกันโดย initializer อื่นโดยไม่คาดคิด
ดังนั้นเพื่อให้แน่ใจว่ากระบวนการกำหนดค่าเริ่มต้นสองขั้นตอนดำเนินการตามที่กำหนดไว้ข้างต้นมีการตรวจสอบความปลอดภัยสี่ประการโดยหนึ่งในนั้นคือ
ตรวจสอบความปลอดภัย 1
ตัวกำหนดค่าเริ่มต้นที่กำหนดต้องตรวจสอบให้แน่ใจว่าคุณสมบัติทั้งหมดที่แนะนำโดยคลาสนั้นถูกเตรียมใช้งานก่อนที่จะมอบสิทธิ์ให้กับตัวเริ่มต้น superclass
ตอนนี้การเริ่มต้นสองเฟสไม่เคยพูดถึงการสั่งซื้อ แต่การตรวจสอบความปลอดภัยนี้super.init
จะแนะนำให้สั่งซื้อหลังจากการเริ่มต้นของคุณสมบัติทั้งหมด
การตรวจสอบความปลอดภัย 1 อาจดูเหมือนไม่เกี่ยวข้องเนื่องจากการ
กำหนดค่าเริ่มต้นแบบสองเฟสป้องกันค่าคุณสมบัติไม่ให้เข้าถึงก่อนที่จะเริ่มต้นได้โดยไม่ต้องมีการตรวจสอบความปลอดภัยนี้ 1
เหมือนในตัวอย่างนี้
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
มีการเตรียมใช้งานคุณสมบัติทั้งหมดก่อนที่จะถูกใช้ ดังนั้นการตรวจสอบความปลอดภัย 1 ดูเหมือนไม่เกี่ยวข้อง
แต่อาจมีอีกสถานการณ์หนึ่งที่ซับซ้อนเล็กน้อย
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)
ผลผลิต:
Shape Name :Triangle
Sides :3
Hypotenuse :12
นี่ถ้าเราได้เรียกว่าsuper.init
ก่อนที่จะตั้งค่าhypotenuse
การsuper.init
โทรจากนั้นก็จะมีการเรียกและตั้งแต่ที่ได้รับการแทนที่มันจะเป็นครั้งแรกทางเลือกในการดำเนินการระดับสามเหลี่ยมprintShapeDescription()
ของการเข้าถึงระดับสามเหลี่ยมไม่ใช่สถานที่ให้บริการที่เป็นตัวเลือกที่ยังคงไม่ได้รับการเริ่มต้นใช้งาน และสิ่งนี้ไม่ได้รับอนุญาตเนื่องจากการกำหนดค่าเริ่มต้นแบบสองเฟสจะป้องกันไม่ให้เข้าถึงค่าคุณสมบัติก่อนที่จะเริ่มต้นprintShapeDescription()
printShapeDescription()
hypotenuse
เพื่อให้แน่ใจว่าการกำหนดค่าเริ่มต้นสองเฟสเสร็จสิ้นตามที่กำหนดไว้จะต้องมีคำสั่งที่เฉพาะเจาะจงสำหรับการโทรsuper.init
และนั่นคือหลังจากการเริ่มต้นคุณสมบัติทั้งหมดที่แนะนำโดยself
คลาสดังนั้นเราจึงต้องมีการตรวจสอบความปลอดภัย 1