Swift - การเริ่มต้น

คลาสโครงสร้างและการแจงนับที่ประกาศไว้ใน Swift 4 จะเริ่มต้นเพื่อเตรียมอินสแตนซ์ของคลาส ค่าเริ่มต้นถูกเตรียมใช้งานสำหรับคุณสมบัติที่จัดเก็บและสำหรับอินสแตนซ์ใหม่ด้วยค่าจะเริ่มต้นเพื่อดำเนินการต่อไป คำสำคัญในการสร้างฟังก์ชันเริ่มต้นดำเนินการโดยวิธี 'init ()' Swift 4 initializer แตกต่างจาก Objective-C ตรงที่ไม่ส่งคืนค่าใด ๆ หน้าที่ของมันคือตรวจสอบการเริ่มต้นของอินสแตนซ์ที่สร้างขึ้นใหม่ก่อนการประมวลผล Swift 4 ยังมีกระบวนการ 'deinitialization' สำหรับการดำเนินการจัดการหน่วยความจำเมื่อยกเลิกการจัดสรรอินสแตนซ์แล้ว

Initializer Role สำหรับคุณสมบัติที่เก็บไว้

คุณสมบัติที่จัดเก็บต้องเตรียมข้อมูลเบื้องต้นให้กับอินสแตนซ์สำหรับคลาสและโครงสร้างก่อนที่จะประมวลผลอินสแตนซ์ คุณสมบัติที่จัดเก็บไว้ใช้ initializer เพื่อกำหนดและเตรียมใช้งานค่าจึงกำจัดความจำเป็นในการเรียกผู้สังเกตการณ์คุณสมบัติ Initializer ถูกใช้ในคุณสมบัติที่เก็บไว้

  • เพื่อสร้างค่าเริ่มต้น

  • เพื่อกำหนดค่าคุณสมบัติเริ่มต้นภายในนิยามคุณสมบัติ

  • ในการเริ่มต้นอินสแตนซ์สำหรับชนิดข้อมูลเฉพาะ 'init ()' จะถูกใช้ ไม่มีการส่งผ่านอาร์กิวเมนต์ภายในฟังก์ชัน init ()

ไวยากรณ์

init() {
   //New Instance initialization goes here
}

ตัวอย่าง

struct rectangle {
   var length: Double
   var breadth: Double
   init() {
      length = 6
      breadth = 12
   }
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area of rectangle is 72.0

ที่นี่โครงสร้าง 'สี่เหลี่ยมผืนผ้า' เริ่มต้นด้วยความยาวและความกว้างของสมาชิกเป็นประเภทข้อมูล 'สองเท่า' วิธี Init () ใช้เพื่อเริ่มต้นค่าสำหรับความยาวสมาชิกที่สร้างขึ้นใหม่และเพิ่มเป็นสองเท่า พื้นที่ของสี่เหลี่ยมผืนผ้าถูกคำนวณและส่งคืนโดยการเรียกฟังก์ชันสี่เหลี่ยมผืนผ้า

การตั้งค่าคุณสมบัติตามค่าเริ่มต้น

ภาษา Swift 4 มีฟังก์ชัน Init () เพื่อเริ่มต้นค่าคุณสมบัติที่เก็บไว้ นอกจากนี้ผู้ใช้ยังมีข้อกำหนดเพื่อเตรียมใช้งานค่าคุณสมบัติตามค่าเริ่มต้นในขณะที่ประกาศคลาสหรือสมาชิกโครงสร้าง เมื่อคุณสมบัติรับค่าเดียวกันตลอดทั้งโปรแกรมเราสามารถประกาศได้ในส่วนการประกาศเพียงอย่างเดียวแทนที่จะเริ่มต้นใน init () การตั้งค่าคุณสมบัติตามค่าเริ่มต้นจะเปิดใช้งานผู้ใช้เมื่อมีการกำหนดการสืบทอดสำหรับคลาสหรือโครงสร้าง

struct rectangle {
   var length = 6
   var breadth = 12
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area of rectangle is 72

ที่นี่แทนที่จะประกาศความยาวและความกว้างใน init () ค่าจะเริ่มต้นในการประกาศเอง

การเริ่มต้นพารามิเตอร์

ในภาษา Swift 4 ผู้ใช้มีข้อกำหนดในการเตรียมใช้งานพารามิเตอร์ซึ่งเป็นส่วนหนึ่งของคำจำกัดความของ initializer โดยใช้ init ()

struct Rectangle {
   var length: Double
   var breadth: Double
   var area: Double
   
   init(fromLength length: Double, fromBreadth breadth: Double) {
      self.length = length
      self.breadth = breadth
      area = length * breadth
   }
   init(fromLeng leng: Double, fromBread bread: Double) {
      self.length = leng
      self.breadth = bread
      area = leng * bread
   }
}

let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: 72.0
area is: 432.0

พารามิเตอร์ภายในและภายนอก

พารามิเตอร์การเริ่มต้นมีทั้งชื่อพารามิเตอร์โลคัลและโกลบอลคล้ายกับพารามิเตอร์ฟังก์ชันและเมธอด การประกาศพารามิเตอร์โลคัลใช้เพื่อเข้าถึงภายในตัวเริ่มต้นและการประกาศพารามิเตอร์ภายนอกใช้เพื่อเรียกตัวเริ่มต้น ตัวเริ่มต้น Swift 4 แตกต่างจากฟังก์ชันและวิธีการเริ่มต้นที่ไม่ได้ระบุว่าตัวเริ่มต้นใช้เรียกฟังก์ชันใด

เพื่อเอาชนะสิ่งนี้ Swift 4 จะแนะนำชื่อภายนอกอัตโนมัติสำหรับแต่ละพารามิเตอร์ใน init () ชื่อภายนอกอัตโนมัตินี้เทียบเท่ากับชื่อโลคัลที่เขียนก่อนทุกพารามิเตอร์การเริ่มต้น

struct Days {
   let sunday, monday, tuesday: Int
   init(sunday: Int, monday: Int, tuesday: Int) {
      self.sunday = sunday
      self.monday = monday
      self.tuesday = tuesday
   }
   init(daysofaweek: Int) {
      sunday = daysofaweek
      monday = daysofaweek
      tuesday = daysofaweek
   }
}

let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")

let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4

พารามิเตอร์ที่ไม่มีชื่อภายนอก

เมื่อไม่จำเป็นต้องใช้ชื่อภายนอกสำหรับการเริ่มต้นขีดล่าง '_' จะใช้เพื่อแทนที่พฤติกรรมเริ่มต้น

struct Rectangle {
   var length: Double
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: 180.0
area is: 370.0
area is: 110.0

ประเภทคุณสมบัติเสริม

เมื่อคุณสมบัติที่เก็บไว้ในบางอินสแตนซ์ไม่ส่งคืนค่าใด ๆ ที่คุณสมบัติถูกประกาศด้วยประเภท 'ทางเลือก' ซึ่งระบุว่า 'ไม่มีค่า' จะถูกส่งกลับสำหรับชนิดนั้น ๆ เมื่อคุณสมบัติที่จัดเก็บถูกประกาศเป็น 'ทางเลือก' มันจะเริ่มต้นค่าโดยอัตโนมัติเป็น 'ศูนย์' ในระหว่างการเตรียมใช้งานเอง

struct Rectangle {
   var length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

การปรับเปลี่ยนคุณสมบัติคงที่ระหว่างการเริ่มต้น

การเริ่มต้นยังช่วยให้ผู้ใช้สามารถแก้ไขค่าของคุณสมบัติคงที่ได้เช่นกัน ในระหว่างการเตรียมใช้งานคุณสมบัติคลาสอนุญาตให้อินสแตนซ์คลาสถูกแก้ไขโดยซูเปอร์คลาสไม่ใช่คลาสย่อย พิจารณาตัวอย่างเช่นในโปรแกรมก่อนหน้า 'length' ถูกประกาศเป็น 'ตัวแปร' ในคลาสหลัก ตัวแปรโปรแกรมด้านล่าง 'ความยาว' ถูกแก้ไขเป็นตัวแปร 'ค่าคงที่'

struct Rectangle {
   let length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

ตัวเริ่มต้นเริ่มต้น

ตัวเริ่มต้นเริ่มต้นจัดเตรียมอินสแตนซ์ใหม่ให้กับคุณสมบัติที่ประกาศทั้งหมดของคลาสพื้นฐานหรือโครงสร้างที่มีค่าดีฟอลต์

class defaultexample {
   var studname: String?
   var stmark = 98
   var pass = true
}
var result = defaultexample()

print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้รับผลลัพธ์ดังต่อไปนี้ -

result is: nil
result is: 98
result is: true

โปรแกรมข้างต้นถูกกำหนดด้วยชื่อคลาสเป็น 'defaultexample' ฟังก์ชั่นสมาชิกสามฟังก์ชันเริ่มต้นโดยค่าเริ่มต้นเป็น 'studname?' เพื่อจัดเก็บค่า 'nil', 'stmark' เป็น 98 และ 'pass' เป็นค่าบูลีน 'true' ในทำนองเดียวกันค่าสมาชิกในคลาสสามารถเริ่มต้นเป็นค่าเริ่มต้นก่อนที่จะประมวลผลประเภทสมาชิกคลาส

Memberwise Initializers สำหรับประเภทโครงสร้าง

เมื่อผู้ใช้ไม่ได้กำหนดค่าเริ่มต้นที่กำหนดเองประเภทโครงสร้างใน Swift 4 จะได้รับ 'memberwise initializer' โดยอัตโนมัติ หน้าที่หลักของมันคือการเตรียมข้อมูลเบื้องต้นให้กับอินสแตนซ์โครงสร้างใหม่ด้วยการเริ่มต้นสมาชิกดีฟอลต์จากนั้นคุณสมบัติของอินสแตนซ์ใหม่จะถูกส่งไปยังการเริ่มต้นของสมาชิกตามชื่อ

struct Rectangle {
   var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Area of rectangle is: 24.0
Area of rectangle is: 32.0

โครงสร้างจะเริ่มต้นโดยค่าเริ่มต้นสำหรับฟังก์ชันการเป็นสมาชิกระหว่างการเริ่มต้นสำหรับ "ความยาว" เป็น "100.0" และ "ความกว้าง" เป็น "200.0" แต่ค่าจะถูกแทนที่ในระหว่างการประมวลผลความยาวและความกว้างของตัวแปรเป็น 24.0 และ 32.0

Initializer Delegation สำหรับ Value types

Initializer Delegation หมายถึงการเรียก initializers จาก initializers อื่น ๆ หน้าที่หลักคือทำหน้าที่เป็นการนำกลับมาใช้ใหม่เพื่อหลีกเลี่ยงการทำซ้ำรหัสในตัวเริ่มต้นหลายตัว

struct Stmark {
   var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
   var m1 = 0.0, m2 = 0.0
}

struct block {
   var average = stdb()
   var result = Stmark()
   init() {}
   init(average: stdb, result: Stmark) {
      self.average = average
      self.result = result
   }

   init(avg: stdb, result: Stmark) {
      let tot = avg.m1 - (result.mark1 / 2)
      let tot1 = avg.m2 - (result.mark2 / 2)
      self.init(average: stdb(m1: tot, m2: tot1), result: result)
   }
}

let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")

let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")

let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

กฎสำหรับการมอบสิทธิ์ Initializer

ประเภทมูลค่า ประเภทคลาส
ไม่รองรับการสืบทอดสำหรับชนิดมูลค่าเช่นโครงสร้างและการแจงนับ การอ้างอิงตัวเริ่มต้นอื่น ๆ ทำได้ผ่าน self.init รองรับการสืบทอด ตรวจสอบค่าคุณสมบัติที่เก็บไว้ทั้งหมดถูกเตรียมใช้งาน

การสืบทอดคลาสและการเริ่มต้น

ประเภทคลาสมีตัวเริ่มต้นสองชนิดเพื่อตรวจสอบว่าคุณสมบัติที่จัดเก็บที่กำหนดไว้ได้รับค่าเริ่มต้นหรือไม่ ได้แก่ ตัวเริ่มต้นที่กำหนดและตัวเริ่มต้นที่สะดวก

Initializers และ Convenience Initializers ที่กำหนด

Initializer ที่กำหนด เครื่องมือเริ่มต้นความสะดวก
ถือเป็นการเริ่มต้นหลักสำหรับคลาส ถือเป็นการสนับสนุนการเริ่มต้นสำหรับคลาส
คุณสมบัติคลาสทั้งหมดได้รับการเตรียมใช้งานและมีการเรียกใช้ตัวเริ่มต้นระดับสูงที่เหมาะสมสำหรับการเตรียมใช้งานเพิ่มเติม ตัวเริ่มต้นที่กำหนดถูกเรียกด้วยตัวเริ่มต้นที่สะดวกในการสร้างอินสแตนซ์คลาสสำหรับกรณีการใช้งานเฉพาะหรือประเภทค่าอินพุต
มีการกำหนด initializer ที่กำหนดไว้อย่างน้อยหนึ่งรายการสำหรับทุกคลาส ไม่จำเป็นต้องมีการกำหนดค่าเริ่มต้นเพื่อความสะดวกเมื่อชั้นเรียนไม่ต้องการตัวเริ่มต้น
Init (พารามิเตอร์) {งบ} อำนวยความสะดวก init (พารามิเตอร์) {งบ}

โปรแกรมสำหรับตัวเริ่มต้นที่กำหนด

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int // new subclass storage
   init(no1 : Int, no2 : Int) {
      self.no2 = no2 // initialization
      super.init(no1:no1) // redirect to superclass
   }
}

let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 10
res is: 10
res is: 20

โปรแกรมสำหรับผู้เริ่มต้นอำนวยความสะดวก

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int
   init(no1 : Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 20
res is: 30
res is: 50

Initializer Inheritance and Overriding

Swift 4 ไม่อนุญาตให้คลาสย่อยสืบทอด superclass initializers สำหรับประเภทสมาชิกตามค่าเริ่มต้น การสืบทอดสามารถใช้ได้กับตัวเริ่มต้นระดับซูเปอร์คลาสเท่านั้นซึ่งจะกล่าวถึงใน Automatic Initializer Inheritance

เมื่อผู้ใช้จำเป็นต้องกำหนด initializers ในซูเปอร์คลาสคลาสย่อยที่มี initializers จะต้องถูกกำหนดโดยผู้ใช้เป็นการใช้งานแบบกำหนดเอง เมื่อการลบล้างจะต้องเกิดขึ้นโดยคลาสย่อยไปยังคีย์เวิร์ด 'override' ระดับซุปเปอร์จะต้องมีการประกาศ

class sides {
   var corners = 4
   var description: String {
      return "\(corners) sides"
   }
}

let rectangle = sides()
print("Rectangle: \(rectangle.description)")

class pentagon: sides {
   override init() {
      super.init()
      corners = 5
   }
}

let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Rectangle: 4 sides
Pentagon: 5 sides

ตัวเริ่มต้นที่กำหนดและสะดวกในการดำเนินการ

class Planet {
   var name: String
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}

let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")

class planets: Planet {
   var count: Int
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Planet name is: Mercury
No Planets like that: [No Planets]

Initializer ล้มเหลว

ผู้ใช้จะต้องได้รับการแจ้งเตือนเมื่อมีความล้มเหลวของตัวเริ่มต้นในขณะที่กำหนดคลาสโครงสร้างหรือค่าการแจงนับ การเริ่มต้นตัวแปรบางครั้งกลายเป็นความล้มเหลวเนื่องจาก

  • ค่าพารามิเตอร์ไม่ถูกต้อง
  • ไม่มีแหล่งภายนอกที่จำเป็น
  • เงื่อนไขที่ป้องกันการเริ่มต้นไม่สำเร็จ

ในการตรวจจับข้อยกเว้นที่เกิดขึ้นโดยวิธีการเริ่มต้น Swift 4 จะสร้างการเริ่มต้นที่ยืดหยุ่นที่เรียกว่า 'ตัวเริ่มต้นที่ล้มเหลว' เพื่อแจ้งให้ผู้ใช้ทราบว่ามีบางสิ่งถูกทิ้งไว้โดยไม่มีใครสังเกตเห็นขณะเริ่มต้นโครงสร้างคลาสหรือสมาชิกการแจงนับ คำหลักที่ใช้จับตัวเริ่มต้นที่ล้มเหลวคือ "init?" นอกจากนี้ตัวเริ่มต้นที่ล้มเหลวและไม่สามารถล้มเหลวไม่สามารถกำหนดด้วยประเภทพารามิเตอร์และชื่อเดียวกันได้

struct studrecord {
   let stname: String
   init?(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}
let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student name is specified
Student name is left blank

ตัวเริ่มต้นที่ล้มเหลวสำหรับการแจงนับ

ภาษา Swift 4 ให้ความยืดหยุ่นในการมีตัวเริ่มต้นที่ล้มเหลวสำหรับการแจงนับเช่นกันเพื่อแจ้งให้ผู้ใช้ทราบเมื่อสมาชิกการแจงนับไม่เหลือจากการกำหนดค่าเริ่มต้น

enum functions {
   case a, b, c, d
   init?(funct: String) {
      switch funct {
      case "one":
         self = .a
      case "two":
         self = .b
      case "three":
         self = .c
      case "four":
         self = .d
      default:
         return nil
      }
   }
}
let result = functions(funct: "two")

if result != nil {
   print("With In Block Two")
}
let badresult = functions(funct: "five")

if badresult == nil {
   print("Block Does Not Exist")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

With In Block Two
Block Does Not Exist

ตัวเริ่มต้นที่ล้มเหลวสำหรับคลาส

ตัวเริ่มต้นที่ล้มเหลวเมื่อประกาศพร้อมกับการแจงนับและโครงสร้างจะแจ้งเตือนความล้มเหลวในการเตรียมใช้งานในทุกสถานการณ์ภายในการนำไปใช้งาน อย่างไรก็ตามตัวเริ่มต้นที่ล้มเหลวในคลาสจะแจ้งเตือนความล้มเหลวหลังจากที่คุณสมบัติที่จัดเก็บถูกตั้งค่าเป็นค่าเริ่มต้นแล้วเท่านั้น

class studrecord {
   let studname: String!
   init?(studname: String) {
      self.studname = studname
      if studname.isEmpty { return nil }
   }
}

if let stname = studrecord(studname: "Failable Initializers") {
   print("Module is \(stname.studname)")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Module is Optional("Failable Initializers")

การลบล้างโปรแกรมเริ่มต้นที่ล้มเหลว

เช่นเดียวกับการเริ่มต้นผู้ใช้ยังมีข้อกำหนดในการแทนที่ตัวเริ่มต้นที่ล้มเหลวของซูเปอร์คลาสภายในคลาสย่อย การเริ่มต้นที่ล้มเหลวในระดับซูเปอร์คลาสยังสามารถถูกแทนที่ด้วยในคลาสย่อยที่ไม่สามารถเริ่มต้นที่ล้มเหลวได้

ตัวเริ่มต้นคลาสย่อยไม่สามารถมอบสิทธิ์ให้กับตัวเริ่มต้นระดับสูงเมื่อแทนที่ตัวเริ่มต้นระดับสูงที่ล้มเหลวด้วยการเริ่มต้นคลาสย่อยที่ไม่สามารถล้มเหลวได้

ตัวเริ่มต้นที่ไม่ล้มเหลวไม่สามารถมอบหมายให้กับตัวเริ่มต้นที่ล้มเหลวได้

โปรแกรมที่ระบุด้านล่างอธิบายถึงตัวเริ่มต้นที่ล้มเหลวและไม่สามารถล้มเหลวได้

class Planet {
   var name: String
   
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")
   
class planets: Planet {
   var count: Int
   
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Planet name is: Mercury
No Planets like that: [No Planets]

เริ่มต้น! Initializer ล้มเหลว

Swift 4 ให้ 'init?' เพื่อกำหนดตัวเริ่มต้นอินสแตนซ์ที่ไม่สามารถเลือกได้ เพื่อกำหนดอินสแตนซ์ทางเลือกที่ไม่ได้ปิดโดยปริยายของประเภทเฉพาะ 'init!' ระบุไว้

struct studrecord {
let stname: String

   init!(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}

let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student name is specified
Student name is left blank

Initializers ที่จำเป็น

ในการประกาศแต่ละคลาสย่อยของคีย์เวิร์ด 'required' initialize จะต้องกำหนดไว้ก่อนฟังก์ชัน init ()

class classA {
   required init() {
      var a = 10
      print(a)
   }
}

class classB: classA {
   required init() {
      var b = 30
      print(b)
   }
}

let res = classA()
let print = classB()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

10
30
10