構(gòu)造過(guò)程是為了使用某個(gè)類(lèi)违柏、結(jié)構(gòu)體或枚舉類(lèi)型的實(shí)例而進(jìn)行的準(zhǔn)備過(guò)程门扇。這個(gè)過(guò)程包含了為實(shí)例中的每個(gè)屬性設(shè)置初始值和為其執(zhí)行必要的準(zhǔn)備和初始化任務(wù)浙滤。
Swift 構(gòu)造函數(shù)使用init()
方法腾誉。
與 Objective-C 中的構(gòu)造器不同贵少,Swift 的構(gòu)造器無(wú)需返回值蚌斩,它們的主要任務(wù)是保證新實(shí)例在第一次使用前完成正確的初始化铆惑。
1. 存儲(chǔ)型屬性的初始賦值
類(lèi)和結(jié)構(gòu)體在實(shí)例創(chuàng)建時(shí),必須為所有存儲(chǔ)型屬性設(shè)置合適的初始值,存儲(chǔ)屬性在構(gòu)造器中賦值時(shí),它們的值是被直接設(shè)置的员魏,不會(huì)觸發(fā)任何屬性觀測(cè)器丑蛤。
- 存儲(chǔ)屬性在構(gòu)造器中賦值流程:
- 創(chuàng)建初始值。
- 在屬性定義中指定默認(rèn)屬性值撕阎。
- 初始化實(shí)例受裹,并調(diào)用
init()
方法。
2. 構(gòu)造器
構(gòu)造器在創(chuàng)建某特定類(lèi)型的新實(shí)例時(shí)調(diào)用虏束。它的最簡(jiǎn)形式類(lèi)似于一個(gè)不帶任何參數(shù)的實(shí)例方法棉饶,以關(guān)鍵字init
命名。
struct rectangle {
var length: Double
var breadth: Double
init() {
length = 6
breadth = 12
}
}
var area = rectangle()
print("矩形面積為 \(area.length*area.breadth)") //矩形面積為 72.0
3. 默認(rèn)屬性值
我們可以在構(gòu)造器中為存儲(chǔ)型屬性設(shè)置初始值镇匀;同樣照藻,也可以在屬性聲明時(shí)為其設(shè)置默認(rèn)值, 使用默認(rèn)值能讓你的構(gòu)造器更簡(jiǎn)潔、更清晰汗侵,且能通過(guò)默認(rèn)值自動(dòng)推導(dǎo)出屬性的類(lèi)型岩梳。
struct rectangle {
// 設(shè)置默認(rèn)值
var length = 6
var breadth = 12
}
var area = rectangle()
print("矩形的面積為 \(area.length*area.breadth)") // 矩形面積為 72
4. 構(gòu)造參數(shù)
你可以在定義構(gòu)造器 init()
時(shí)提供構(gòu)造參數(shù)
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("面積為: \(ar.area)")
let are = Rectangle(fromLeng: 36, fromBread: 12)
print("面積為: \(are.area)")
以上程序執(zhí)行輸出結(jié)果為:
面積為: 72.0
面積為: 432.0
5. 內(nèi)部和外部參數(shù)名
跟函數(shù)和方法參數(shù)相同,構(gòu)造參數(shù)也存在一個(gè)在構(gòu)造器內(nèi)部使用的參數(shù)名字和一個(gè)在調(diào)用構(gòu)造器時(shí)使用的外部參數(shù)名字晃择。
然而,構(gòu)造器并不像函數(shù)和方法那樣在括號(hào)前有一個(gè)可辨別的名字也物。所以在調(diào)用構(gòu)造器時(shí)宫屠,主要通過(guò)構(gòu)造器中的參數(shù)名和類(lèi)型來(lái)確定需要調(diào)用的構(gòu)造器。
如果你在定義構(gòu)造器時(shí)沒(méi)有提供參數(shù)的外部名字滑蚯,Swift 會(huì)為每個(gè)構(gòu)造器的參數(shù)自動(dòng)生成一個(gè)跟內(nèi)部名字相同的外部名浪蹂。
struct Color {
let red, green, blue: Double
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
init(white: Double) {
red = white
green = white
blue = white
}
}
// 創(chuàng)建一個(gè)新的Color實(shí)例,通過(guò)三種顏色的外部參數(shù)名來(lái)傳值告材,并調(diào)用構(gòu)造器
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
print("red 值為: \(magenta.red)")
print("green 值為: \(magenta.green)")
print("blue 值為: \(magenta.blue)")
// 創(chuàng)建一個(gè)新的Color實(shí)例坤次,通過(guò)三種顏色的外部參數(shù)名來(lái)傳值,并調(diào)用構(gòu)造器
let halfGray = Color(white: 0.5)
print("red 值為: \(halfGray.red)")
print("green 值為: \(halfGray.green)")
print("blue 值為: \(halfGray.blue)")
// red 值為: 1.0
// green 值為: 0.0
// blue 值為: 1.0
// red 值為: 0.5
// green 值為: 0.5
// blue 值為: 0.5
沒(méi)有外部名稱(chēng)參數(shù)
如果你不希望為構(gòu)造器的某個(gè)參數(shù)提供外部名字斥赋,你可以使用下劃線_來(lái)顯示描述它的外部名缰猴。
struct Rectangle {
var length: Double
init(frombreadth breadth: Double) {
length = breadth * 10
}
init(frombre bre: Double) {
length = bre * 30
}
//不提供外部名字
init(_ area: Double) {
length = area
}
}
// 調(diào)用不提供外部名字
let rectarea = Rectangle(180.0)
print("面積為: \(rectarea.length)")
// 調(diào)用不提供外部名字
let rearea = Rectangle(370.0)
print("面積為: \(rearea.length)")
// 調(diào)用不提供外部名字
let recarea = Rectangle(110.0)
print("面積為: \(recarea.length)")
以上程序執(zhí)行輸出結(jié)果為:
// 面積為: 180.0
// 面積為: 370.0
// 面積為: 110.0
6. 可選屬性類(lèi)型
如果你定制的類(lèi)型包含一個(gè)邏輯上允許取值為空的存儲(chǔ)型屬性,你都需要將它定義為可選類(lèi)型optional type(可選屬性類(lèi)型),當(dāng)存儲(chǔ)屬性聲明為可選時(shí)疤剑,將自動(dòng)初始化為空 nil滑绒。
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("面積為:\(rectarea.length)")
let rearea = Rectangle(370.0)
print("面積為:\(rearea.length)")
let recarea = Rectangle(110.0)
print("面積為:\(recarea.length)")
// 面積為:Optional(180.0)
// 面積為:Optional(370.0)
// 面積為:Optional(110.0)
7. 構(gòu)造過(guò)程中修改常量屬性
只要在構(gòu)造過(guò)程結(jié)束前常量的值能確定,你可以在構(gòu)造過(guò)程中的任意時(shí)間點(diǎn)修改常量屬性的值隘膘。
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("面積為:\(rectarea.length)")
let rearea = Rectangle(370.0)
print("面積為:\(rearea.length)")
let recarea = Rectangle(110.0)
print("面積為:\(recarea.length)")
以上程序執(zhí)行輸出結(jié)果為:
// 面積為:Optional(180.0)
// 面積為:Optional(370.0)
// 面積為:Optional(110.0)
8. 默認(rèn)構(gòu)造器
默認(rèn)構(gòu)造器將簡(jiǎn)單的創(chuàng)建一個(gè)所有屬性值都設(shè)置為默認(rèn)值的實(shí)例:
以下實(shí)例中疑故,ShoppingListItem類(lèi)中的所有屬性都有默認(rèn)值,且它是沒(méi)有父類(lèi)的基類(lèi)弯菊,它將自動(dòng)獲得一個(gè)可以為所有屬性設(shè)置默認(rèn)值的默認(rèn)構(gòu)造器
class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()
print("名字為: \(item.name)")
print("數(shù)理為: \(item.quantity)")
print("是否付款: \(item.purchased)")
// 名字為: nil
// 數(shù)理為: 1
// 是否付款: false
9. 結(jié)構(gòu)體的逐一成員構(gòu)造器
如果結(jié)構(gòu)體對(duì)所有存儲(chǔ)型屬性提供了默認(rèn)值且自身沒(méi)有提供定制的構(gòu)造器纵势,它們能自動(dòng)獲得一個(gè)逐一成員構(gòu)造器。
struct Rectangle {
var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)
print("矩形的面積: \(area.length)")
print("矩形的面積: \(area.breadth)")
// 由于這兩個(gè)存儲(chǔ)型屬性都有默認(rèn)值,結(jié)構(gòu)體 Rectangle 自動(dòng)獲得了一個(gè)逐一成員構(gòu)造器 init(width:height:)钦铁。 你可以用它來(lái)為 Rectangle 創(chuàng)建新的實(shí)例软舌。
// 名字為: nil
// 矩形的面積: 24.0
// 矩形的面積: 32.0
10. 值類(lèi)型的構(gòu)造器代理
構(gòu)造器可以通過(guò)調(diào)用其它構(gòu)造器來(lái)完成實(shí)例的部分構(gòu)造過(guò)程。這一過(guò)程稱(chēng)為構(gòu)造器代理育瓜,它能減少多個(gè)構(gòu)造器間的代碼重復(fù)葫隙。
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
init() {}
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
// origin和size屬性都使用定義時(shí)的默認(rèn)值Point(x: 0.0, y: 0.0)和Size(width: 0.0, height: 0.0):
let basicRect = Rect()
print("Size 結(jié)構(gòu)體初始值: \(basicRect.size.width, basicRect.size.height) ")
print("Rect 結(jié)構(gòu)體初始值: \(basicRect.origin.x, basicRect.origin.y) ")
// 將origin和size的參數(shù)值賦給對(duì)應(yīng)的存儲(chǔ)型屬性
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))
print("Size 結(jié)構(gòu)體初始值: \(originRect.size.width, originRect.size.height) ")
print("Rect 結(jié)構(gòu)體初始值: \(originRect.origin.x, originRect.origin.y) ")
//先通過(guò)center和size的值計(jì)算出origin的坐標(biāo)。
//然后再調(diào)用(或代理給)init(origin:size:)構(gòu)造器來(lái)將新的origin和size值賦值到對(duì)應(yīng)的屬性中
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
size: Size(width: 3.0, height: 3.0))
print("Size 結(jié)構(gòu)體初始值: \(centerRect.size.width, centerRect.size.height) ")
print("Rect 結(jié)構(gòu)體初始值: \(centerRect.origin.x, centerRect.origin.y) ")
以上程序執(zhí)行輸出結(jié)果為:
Size 結(jié)構(gòu)體初始值: (0.0, 0.0)
Rect 結(jié)構(gòu)體初始值: (0.0, 0.0)
Size 結(jié)構(gòu)體初始值: (5.0, 5.0)
Rect 結(jié)構(gòu)體初始值: (2.0, 2.0)
Size 結(jié)構(gòu)體初始值: (3.0, 3.0)
Rect 結(jié)構(gòu)體初始值: (2.5, 2.5)
11. 構(gòu)造器代理規(guī)則
值類(lèi)型 | 類(lèi)類(lèi)型 |
---|---|
不支持繼承躏仇,所以構(gòu)造器代理的過(guò)程相對(duì)簡(jiǎn)單恋脚,因?yàn)樗鼈冎荒艽斫o本身提供的其它構(gòu)造器。 你可以使用self.init在自定義的構(gòu)造器中引用其它的屬于相同值類(lèi)型的構(gòu)造器焰手。 | 可以繼承自其它類(lèi),這意味著類(lèi)有責(zé)任保證其所有繼承的存儲(chǔ)型屬性在構(gòu)造時(shí)也能正確的初始化糟描。 |
12. 類(lèi)的繼承和構(gòu)造過(guò)程
Swift 提供了兩種類(lèi)型的類(lèi)構(gòu)造器來(lái)確保所有類(lèi)實(shí)例中存儲(chǔ)型屬性都能獲得初始值,它們分別是指定構(gòu)造器和便利構(gòu)造器书妻。
指定構(gòu)造器 | 便利構(gòu)造器 |
---|---|
類(lèi)中最主要的構(gòu)造器 | 類(lèi)中比較次要的船响、輔助型的構(gòu)造器 |
初始化類(lèi)中提供的所有屬性,并根據(jù)父類(lèi)鏈往上調(diào)用父類(lèi)的構(gòu)造器來(lái)實(shí)現(xiàn)父類(lèi)的初始化躲履。 | 可以定義便利構(gòu)造器來(lái)調(diào)用同一個(gè)類(lèi)中的指定構(gòu)造器见间,并為其參數(shù)提供默認(rèn)值。你也可以定義便利構(gòu)造器來(lái)創(chuàng)建一個(gè)特殊用途或特定輸入的實(shí)例工猜。 |
每一個(gè)類(lèi)都必須擁有至少一個(gè)指定構(gòu)造器 只在必要的時(shí)候?yàn)轭?lèi)提供便利構(gòu)造器
Init(parameters) {
statements
}
convenience init(parameters) {
statements
}
// 指定構(gòu)造器實(shí)例
class mainClass {
var no1 : Int // 局部存儲(chǔ)變量
init(no1 : Int) {
self.no1 = no1 // 初始化
}
}
class subClass : mainClass {
var no2 : Int // 新的子類(lèi)存儲(chǔ)變量
init(no1 : Int, no2 : Int) {
self.no2 = no2 // 初始化
super.init(no1:no1) // 初始化超類(lèi)
}
}
let res = mainClass(no1: 10)
let res2 = subClass(no1: 10, no2: 20)
print("res 為: \(res.no1)")
print("res2 為: \(res2.no1)")
print("res2 為: \(res2.no2)")
// res 為: 10
// res 為: 10
// res 為: 20
13. 便利構(gòu)造器實(shí)例
便利構(gòu)造器是指提供不同的API接口米诉,但內(nèi)部調(diào)用真正在做初始化工作的構(gòu)造方法,需要使用convenience
關(guān)鍵字篷帅。
class mainClass {
var no1 : Int // 局部存儲(chǔ)變量
init(no1 : Int) {
self.no1 = no1 // 初始化
}
}
class subClass : mainClass {
var no2 : Int
init(no1 : Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// 便利方法只需要一個(gè)參數(shù)
override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
let res2 = subClass(no1: 30, no2: 50)
print("res 為: \(res.no1)")
print("res2 為: \(res2.no1)")
print("res2 為: \(res2.no2)")
// res 為: 20
// res2 為: 30
// res2 為: 50
14. 構(gòu)造器的繼承和重載
Swift 中的子類(lèi)不會(huì)默認(rèn)繼承父類(lèi)的構(gòu)造器,類(lèi)的構(gòu)造器僅在確定和安全的情況下被繼承,當(dāng)你重寫(xiě)一個(gè)父類(lèi)指定構(gòu)造器時(shí)史侣,你需要寫(xiě)override
修飾符。
class SuperClass {
var corners = 4
var description: String {
return "\(corners) 邊"
}
}
let rectangle = SuperClass()
print("矩形: \(rectangle.description)")
class SubClass: SuperClass {
override init() { //重載構(gòu)造器
super.init()
corners = 5
}
}
let subClass = SubClass()
print("五角型: \(subClass.description)")
// 矩形: 4 邊
// 五角型: 5 邊
15. 指定構(gòu)造器和便利構(gòu)造器實(shí)例
接下來(lái)的例子將在操作中展示指定構(gòu)造器魏身、便利構(gòu)造器和自動(dòng)構(gòu)造器的繼承,它定義了包含兩個(gè)個(gè)類(lèi)MainClass惊橱、SubClass的類(lèi)層次結(jié)構(gòu),并將演示它們的構(gòu)造器是如何相互作用的箭昵。
class MainClass {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[匿名]")
}
}
let main = MainClass(name: "Pikachu")
print("MainClass 名字為: \(main.name)")
let main2 = MainClass()
print("沒(méi)有對(duì)應(yīng)名字: \(main2.name)")
class SubClass: MainClass {
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)
}
}
let sub = SubClass(name: "Pikachu")
print("MainClass 名字為: \(sub.name)")
let sub2 = SubClass(name: "Pikachu", count: 3)
print("count 變量: \(sub2.count)")
// MainClass 名字為: Pikachu
// 沒(méi)有對(duì)應(yīng)名字: [匿名]
// MainClass 名字為: Pikachu
// count 變量: 3
16. 類(lèi)的可失敗構(gòu)造器
如果一個(gè)類(lèi)税朴,結(jié)構(gòu)體或枚舉類(lèi)型的對(duì)象,在構(gòu)造自身的過(guò)程中有可能失敗宙枷,則為其定義一個(gè)可失敗構(gòu)造器掉房。
變量初始化失敗可能的原因有:
- 傳入無(wú)效的參數(shù)值。
- 缺少某種所需的外部資源慰丛。
- 沒(méi)有滿足特定條件卓囚。
為了妥善處理這種構(gòu)造過(guò)程中可能會(huì)失敗的情況,你可以在一個(gè)類(lèi),結(jié)構(gòu)體或是枚舉類(lèi)型的定義中诅病,添加一個(gè)或多個(gè)可失敗構(gòu)造器哪亿。其語(yǔ)法為在init關(guān)鍵字后面加添問(wèn)號(hào)(init?)粥烁。
/*
定義了一個(gè)名為Animal的結(jié)構(gòu)體,其中有一個(gè)名為species的蝇棉,String類(lèi)型的常量屬性讨阻。
同時(shí)該結(jié)構(gòu)體還定義了一個(gè),帶一個(gè)String類(lèi)型參數(shù)species的,可失敗構(gòu)造器篡殷。這個(gè)可失敗構(gòu)造器钝吮,被用來(lái)檢查傳入的參數(shù)是否為一個(gè)空字符串,如果為空字符串板辽,則該可失敗構(gòu)造器奇瘦,構(gòu)建對(duì)象失敗,否則成功劲弦。
*/
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
//通過(guò)該可失敗構(gòu)造器來(lái)構(gòu)建一個(gè)Animal的對(duì)象耳标,并檢查其構(gòu)建過(guò)程是否成功
// someCreature 的類(lèi)型是 Animal? 而不是 Animal
let someCreature = Animal(species: "長(zhǎng)頸鹿")
// 打印 "動(dòng)物初始化為長(zhǎng)頸鹿"
if let giraffe = someCreature {
print("動(dòng)物初始化為\(giraffe.species)")
}
// 動(dòng)物初始化為長(zhǎng)頸鹿
17. 枚舉類(lèi)型的可失敗構(gòu)造器
你可以通過(guò)構(gòu)造一個(gè)帶一個(gè)或多個(gè)參數(shù)的可失敗構(gòu)造器來(lái)獲取枚舉類(lèi)型中特定的枚舉成員。
/*
定義了一個(gè)名為T(mén)emperatureUnit的枚舉類(lèi)型邑跪。其中包含了三個(gè)可能的枚舉成員(Kelvin次坡,Celsius,和 Fahrenheit)和一個(gè)被用來(lái)找到Character值所對(duì)應(yīng)的枚舉成員的可失敗構(gòu)造器:
*/
enum TemperatureUnit {
// 開(kāi)爾文画畅,攝氏砸琅,華氏
case Kelvin, Celsius, Fahrenheit
init?(symbol: Character) {
switch symbol {
case "K":
self = .Kelvin
case "C":
self = .Celsius
case "F":
self = .Fahrenheit
default:
return nil
}
}
}
let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
print("這是一個(gè)已定義的溫度單位,所以初始化成功轴踱。")
}
let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
print("這不是一個(gè)已定義的溫度單位明棍,所以初始化失敗。")
}
// 這是一個(gè)已定義的溫度單位寇僧,所以初始化成功。
// 這不是一個(gè)已定義的溫度單位沸版,所以初始化失敗嘁傀。
18. 類(lèi)的可失敗構(gòu)造器
值類(lèi)型(如結(jié)構(gòu)體或枚舉類(lèi)型)的可失敗構(gòu)造器,對(duì)何時(shí)何地觸發(fā)構(gòu)造失敗這個(gè)行為沒(méi)有任何的限制视粮。但是類(lèi)的可失敗構(gòu)造器只能在所有的類(lèi)屬性被初始化后和所有類(lèi)之間的構(gòu)造器之間的代理調(diào)用發(fā)生完后觸發(fā)失敗行為细办。
/*
下例子中,定義了一個(gè)名為 StudRecord 的類(lèi)蕾殴,因?yàn)?studname 屬性是一個(gè)常量笑撞,所以一旦 StudRecord 類(lèi)構(gòu)造成功,studname 屬性肯定有一個(gè)非nil的值钓觉。
*/
class StudRecord {
let studname: String!
init?(studname: String) {
self.studname = studname
if studname.isEmpty { return nil }
}
}
if let stname = StudRecord(studname: "失敗構(gòu)造器") {
print("模塊為 \(stname.studname)")
}
// 模塊為 失敗構(gòu)造器
19. 重寫(xiě)一個(gè)可失敗構(gòu)造器
就如同其它構(gòu)造器一樣茴肥,你也可以用子類(lèi)的可失敗構(gòu)造器重寫(xiě)基類(lèi)的可失敗構(gòu)造器。你也可以用子類(lèi)的非可失敗構(gòu)造器覆蓋一個(gè)基類(lèi)的可失敗構(gòu)造器荡灾。
你可以用一個(gè)非可失敗構(gòu)造器覆蓋一個(gè)可失敗構(gòu)造器瓤狐,但反過(guò)來(lái)卻行不通瞬铸。
一個(gè)非可失敗的構(gòu)造器永遠(yuǎn)也不能代理調(diào)用一個(gè)可失敗構(gòu)造器。
class Planet {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[No Planets]")
}
}
let plName = Planet(name: "Mercury")
print("行星的名字是: \(plName.name)")
let noplName = Planet()
print("沒(méi)有這個(gè)名字的行星: \(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)
}
}
// 行星的名字是: Mercury
// 沒(méi)有這個(gè)名字的行星: [No Planets]
20. 可失敗構(gòu)造器 init!
通常來(lái)說(shuō)我們通過(guò)在init關(guān)鍵字后添加問(wèn)號(hào)的方式(init?)來(lái)定義一個(gè)可失敗構(gòu)造器础锐,但你也可以使用通過(guò)在init后面添加驚嘆號(hào)的方式來(lái)定義一個(gè)可失敗構(gòu)造器(init!)嗓节。實(shí)例如下:
struct StudRecord {
let stname: String
init!(stname: String) {
if stname.isEmpty {return nil }
self.stname = stname
}
}
let stmark = StudRecord(stname: "Pikachu")
if let name = stmark {
print("指定了學(xué)生名")
}
let blankname = StudRecord(stname: "")
if blankname == nil {
print("學(xué)生名為空")
}
// 指定了學(xué)生名
// 學(xué)生名為空