Swift 構(gòu)造過(guò)程
構(gòu)造過(guò)程是為了使用某個(gè)類、結(jié)構(gòu)體或枚舉類型的實(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í)例在第一次使用前完成正確的初始化。
類實(shí)例也可以通過(guò)定義析構(gòu)器(deinitializer)在類實(shí)例釋放之前執(zhí)行清理內(nèi)存的工作。
存儲(chǔ)型屬性的初始賦值
類和結(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() 方法。
構(gòu)造器
構(gòu)造器在創(chuàng)建某特定類型的新實(shí)例時(shí)調(diào)用。它的最簡(jiǎn)形式類似于一個(gè)不帶任何參數(shù)的實(shí)例方法,以關(guān)鍵字init命名。
語(yǔ)法
init() { // 實(shí)例化后執(zhí)行的代碼 }
實(shí)例
以下結(jié)構(gòu)體定義了一個(gè)不帶參數(shù)的構(gòu)造器 init,并在里面將存儲(chǔ)型屬性 length 和 breadth 的值初始化為 6 和 12:
struct rectangle { var length: Double var breadth: Double init() { length = 6 breadth = 12 } } var area = rectangle() print("矩形面積為 \(area.length*area.breadth)")
以上程序執(zhí)行輸出結(jié)果為:
矩形面積為 72.0
默認(rèn)屬性值
我們可以在構(gòu)造器中為存儲(chǔ)型屬性設(shè)置初始值;同樣,也可以在屬性聲明時(shí)為其設(shè)置默認(rèn)值。
使用默認(rèn)值能讓你的構(gòu)造器更簡(jiǎn)潔、更清晰,且能通過(guò)默認(rèn)值自動(dòng)推導(dǎo)出屬性的類型。
以下實(shí)例我們?cè)趯傩月暶鲿r(shí)為其設(shè)置默認(rèn)值:
struct rectangle { // 設(shè)置默認(rèn)值 var length = 6 var breadth = 12 } var area = rectangle() print("矩形的面積為 \(area.length*area.breadth)")
以上程序執(zhí)行輸出結(jié)果為:
矩形面積為 72
構(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
內(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)確定需要調(diào)用的構(gòu)造器。
如果你在定義構(gòu)造器時(shí)沒有提供參數(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)")
以上程序執(zhí)行輸出結(jié)果為:
red 值為: 1.0 green 值為: 0.0 blue 值為: 1.0 red 值為: 0.5 green 值為: 0.5 blue 值為: 0.5
沒有外部名稱參數(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
可選屬性類型
如果你定制的類型包含一個(gè)邏輯上允許取值為空的存儲(chǔ)型屬性,你都需要將它定義為可選類型optional type(可選屬性類型)。
當(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)")
以上程序執(zhí)行輸出結(jié)果為:
面積為:Optional(180.0) 面積為:Optional(370.0) 面積為:Optional(110.0)
構(gòu)造過(guò)程中修改常量屬性
只要在構(gòu)造過(guò)程結(jié)束前常量的值能確定,你可以在構(gòu)造過(guò)程中的任意時(shí)間點(diǎn)修改常量屬性的值。
對(duì)某個(gè)類實(shí)例來(lái)說(shuō),它的常量屬性只能在定義它的類的構(gòu)造過(guò)程中修改;不能在子類中修改。
盡管 length 屬性現(xiàn)在是常量,我們?nèi)匀豢梢栽谄漕惖臉?gòu)造器中設(shè)置它的值:
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)
默認(rèn)構(gòu)造器
默認(rèn)構(gòu)造器將簡(jiǎn)單的創(chuàng)建一個(gè)所有屬性值都設(shè)置為默認(rèn)值的實(shí)例:
以下實(shí)例中,ShoppingListItem類中的所有屬性都有默認(rèn)值,且它是沒有父類的基類,它將自動(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)")
以上程序執(zhí)行輸出結(jié)果為:
名字為: nil 數(shù)理為: 1 是否付款: false
結(jié)構(gòu)體的逐一成員構(gòu)造器
如果結(jié)構(gòu)體對(duì)所有存儲(chǔ)型屬性提供了默認(rèn)值且自身沒有提供定制的構(gòu)造器,它們能自動(dòng)獲得一個(gè)逐一成員構(gòu)造器。
我們?cè)谡{(diào)用逐一成員構(gòu)造器時(shí),通過(guò)與成員屬性名相同的參數(shù)名進(jìn)行傳值來(lái)完成對(duì)成員屬性的初始賦值。
下面例子中定義了一個(gè)結(jié)構(gòu)體 Rectangle,它包含兩個(gè)屬性 length 和 breadth。Swift 可以根據(jù)這兩個(gè)屬性的初始賦值100.0 、200.0自動(dòng)推導(dǎo)出它們的類型Double。
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í)例。
以上程序執(zhí)行輸出結(jié)果為:
名字為: nil 矩形的面積: 24.0 矩形的面積: 32.0
值類型的構(gòu)造器代理
構(gòu)造器可以通過(guò)調(diào)用其它構(gòu)造器來(lái)完成實(shí)例的部分構(gòu)造過(guò)程。這一過(guò)程稱為構(gòu)造器代理,它能減少多個(gè)構(gòu)造器間的代碼重復(fù)。
以下實(shí)例中,Rect 結(jié)構(gòu)體調(diào)用了 Size 和 Point 的構(gòu)造過(guò)程:
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)
構(gòu)造器代理規(guī)則
值類型 | 類類型 |
---|---|
不支持繼承,所以構(gòu)造器代理的過(guò)程相對(duì)簡(jiǎn)單,因?yàn)樗鼈冎荒艽斫o本身提供的其它構(gòu)造器。 你可以使用self.init在自定義的構(gòu)造器中引用其它的屬于相同值類型的構(gòu)造器。 | 它可以繼承自其它類,這意味著類有責(zé)任保證其所有繼承的存儲(chǔ)型屬性在構(gòu)造時(shí)也能正確的初始化。 |
類的繼承和構(gòu)造過(guò)程
Swift 提供了兩種類型的類構(gòu)造器來(lái)確保所有類實(shí)例中存儲(chǔ)型屬性都能獲得初始值,它們分別是指定構(gòu)造器和便利構(gòu)造器。
指定構(gòu)造器 | 便利構(gòu)造器 |
類中最主要的構(gòu)造器 | 類中比較次要的、輔助型的構(gòu)造器 |
初始化類中提供的所有屬性,并根據(jù)父類鏈往上調(diào)用父類的構(gòu)造器來(lái)實(shí)現(xiàn)父類的初始化。 | 可以定義便利構(gòu)造器來(lái)調(diào)用同一個(gè)類中的指定構(gòu)造器,并為其參數(shù)提供默認(rèn)值。你也可以定義便利構(gòu)造器來(lái)創(chuàng)建一個(gè)特殊用途或特定輸入的實(shí)例。 |
每一個(gè)類都必須擁有至少一個(gè)指定構(gòu)造器 | 只在必要的時(shí)候?yàn)轭愄峁┍憷麡?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 // 新的子類存儲(chǔ)變量 init(no1 : Int, no2 : Int) { self.no2 = no2 // 初始化 super.init(no1:no1) // 初始化超類 } } let res = mainClass(no1: 10) let res2 = subClass(no1: 10, no2: 20) print("res 為: \(res.no1)") print("res2 為: \(res2.no1)") print("res2 為: \(res2.no2)")
以上程序執(zhí)行輸出結(jié)果為:
res 為: 10 res 為: 10 res 為: 20
便利構(gòu)造器實(shí)例
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)")
以上程序執(zhí)行輸出結(jié)果為:
res 為: 20 res2 為: 30 res2 為: 50
構(gòu)造器的繼承和重載
Swift 中的子類不會(huì)默認(rèn)繼承父類的構(gòu)造器。
父類的構(gòu)造器僅在確定和安全的情況下被繼承。
當(dāng)你重寫一個(gè)父類指定構(gòu)造器時(shí),你需要寫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)")
以上程序執(zhí)行輸出結(jié)果為:
矩形: 4 邊 五角型: 5 邊
指定構(gòu)造器和便利構(gòu)造器實(shí)例
接下來(lái)的例子將在操作中展示指定構(gòu)造器、便利構(gòu)造器和自動(dòng)構(gòu)造器的繼承。
它定義了包含兩個(gè)個(gè)類MainClass、SubClass的類層次結(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: "W3CSchool") print("MainClass 名字為: \(main.name)") let main2 = MainClass() print("沒有對(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: "W3CSchool") print("MainClass 名字為: \(sub.name)") let sub2 = SubClass(name: "W3CSchool", count: 3) print("count 變量: \(sub2.count)")
以上程序執(zhí)行輸出結(jié)果為:
MainClass 名字為: W3CSchool 沒有對(duì)應(yīng)名字: [匿名] MainClass 名字為: W3CSchool count 變量: 3
類的可失敗構(gòu)造器
如果一個(gè)類,結(jié)構(gòu)體或枚舉類型的對(duì)象,在構(gòu)造自身的過(guò)程中有可能失敗,則為其定義一個(gè)可失敗構(gòu)造器。
變量初始化失敗可能的原因有:
傳入無(wú)效的參數(shù)值。
缺少某種所需的外部資源。
沒有滿足特定條件。
為了妥善處理這種構(gòu)造過(guò)程中可能會(huì)失敗的情況。
你可以在一個(gè)類,結(jié)構(gòu)體或是枚舉類型的定義中,添加一個(gè)或多個(gè)可失敗構(gòu)造器。其語(yǔ)法為在init關(guān)鍵字后面加添問(wèn)號(hào)(init?)。
實(shí)例
下例中,定義了一個(gè)名為Animal的結(jié)構(gòu)體,其中有一個(gè)名為species的,String類型的常量屬性。
同時(shí)該結(jié)構(gòu)體還定義了一個(gè),帶一個(gè)String類型參數(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 的類型是 Animal? 而不是 Animal let someCreature = Animal(species: "長(zhǎng)頸鹿") // 打印 "動(dòng)物初始化為長(zhǎng)頸鹿" if let giraffe = someCreature { print("動(dòng)物初始化為\(giraffe.species)") }
以上程序執(zhí)行輸出結(jié)果為:
動(dòng)物初始化為長(zhǎng)頸鹿
枚舉類型的可失敗構(gòu)造器
你可以通過(guò)構(gòu)造一個(gè)帶一個(gè)或多個(gè)參數(shù)的可失敗構(gòu)造器來(lái)獲取枚舉類型中特定的枚舉成員。
實(shí)例
下例中,定義了一個(gè)名為TemperatureUnit的枚舉類型。其中包含了三個(gè)可能的枚舉成員(Kelvin,Celsius,和 Fahrenheit)和一個(gè)被用來(lái)找到Character值所對(duì)應(yīng)的枚舉成員的可失敗構(gòu)造器:
enum TemperatureUnit { // 開爾文,攝氏,華氏 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è)已定義的溫度單位,所以初始化失敗。") }
以上程序執(zhí)行輸出結(jié)果為:
這是一個(gè)已定義的溫度單位,所以初始化成功。 這不是一個(gè)已定義的溫度單位,所以初始化失敗。
類的可失敗構(gòu)造器
值類型(如結(jié)構(gòu)體或枚舉類型)的可失敗構(gòu)造器,對(duì)何時(shí)何地觸發(fā)構(gòu)造失敗這個(gè)行為沒有任何的限制。
但是,類的可失敗構(gòu)造器只能在所有的類屬性被初始化后和所有類之間的構(gòu)造器之間的代理調(diào)用發(fā)生完后觸發(fā)失敗行為。
實(shí)例
下例子中,定義了一個(gè)名為 StudRecord 的類,因?yàn)?studname 屬性是一個(gè)常量,所以一旦 StudRecord 類構(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)") }
以上程序執(zhí)行輸出結(jié)果為:
模塊為 失敗構(gòu)造器
覆蓋一個(gè)可失敗構(gòu)造器
就如同其它構(gòu)造器一樣,你也可以用子類的可失敗構(gòu)造器覆蓋基類的可失敗構(gòu)造器。
者你也可以用子類的非可失敗構(gòu)造器覆蓋一個(gè)基類的可失敗構(gòu)造器。
你可以用一個(gè)非可失敗構(gòu)造器覆蓋一個(gè)可失敗構(gòu)造器,但反過(guò)來(lái)卻行不通。
一個(gè)非可失敗的構(gòu)造器永遠(yuǎn)也不能代理調(diào)用一個(gè)可失敗構(gòu)造器。
實(shí)例
以下實(shí)例描述了可失敗與非可失敗構(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("沒有這個(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) } }
以上程序執(zhí)行輸出結(jié)果為:
行星的名字是: Mercury 沒有這個(gè)名字的行星: [No Planets]
可失敗構(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: "W3CSchool") if let name = stmark { print("指定了學(xué)生名") } let blankname = StudRecord(stname: "") if blankname == nil { print("學(xué)生名為空") }
以上程序執(zhí)行輸出結(jié)果為:
指定了學(xué)生名 學(xué)生名為空
更多建議: