/*************** 初始化 *******************/
// 在使用 實類,結構體,枚舉之前都需要初始化
// 初始化過程需要給 存儲屬性設值, 并做其他初始化操作.
// 和oc 不同, swift 初始化并不反回值.
// 初始化是為了確保這個實類在第一次使用的前已經做好了準備
// 初始化給存儲屬性設值
// 類和結構體在初始化時必須給所有存儲屬性賦值. 存儲屬性不允許有不確定值得狀態
// 也可以在定義存儲屬性時給它設一個默認值, 該操作不會觸發觀察者模式
struct Fahrenheit{
var temperature: Double
init(){
temperature = 32.0// 初始化設置默認值
}
}
var f = Fahrenheit()
print("The default temperature is \(f.temperature)")
//Prints "The default temperature is 32.0 Fahrenheit"
// 設置存儲屬性默認值
// 屬性申明的時候就設置默認值
struct FahrenheitA{
var temperature = 32.0
}
// 建議多使用申明默認值 而不是 初始化設置默認值
//---------自定義初始化-----
struct Celsius{
var temperatureinCelsius:Double
init(fromFahrenheit fahrenheit: Double){
temperatureinCelsius = (fahrenheit - 32.0)/1.8
}
init(fromKelvin kelvin:Double){
temperatureinCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boi9lingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0
//-----------參數名 和參數標簽-------
// 在初始化中, 默認 參數名就是標簽名, 方法內部和外部都可以用
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
}
}
let magenta = Color(red: 1.0, green:0.0, blue: 1.0)
let halfGray = Color(white: 0.5)
//let veryGreen = Color(0.0, 1.0, 0.0)
// 報錯, Missing argument labels 'red:green:blue:' in call
// 那么如何在初始化的時候 不顯示參數名呢?
// 定義初始化方法時 ,用下劃線 代表表情參數就可
struct CelsiusA {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
init(_ celsius: Double) {
temperatureInCelsius = celsius
}
}
let bodyTemperature = CelsiusA(37.0)
// bodyTemperature.temperatureInCelsius is 37.0
// --------可選屬性值---------
// 變量名:數據類型?
// 可選屬性 在初始化時可以為 nil
class SurveyQuestion{
var text: String
var response: String?
init(text:String){
self.text = text
}
func ask(){
print(text)
}
}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
//Prints "Do you like cheese?"
cheeseQuestion.response = "Yes, I do like cheese"
//---------- 初始化時 使用 靜態常量屬性 ---------
// 初始化時可以更改常量屬性的值?
class SurveyQuestionA{
let text: String
var response:String?
init(text: String) {
self.text = text
}
func ask(){
print(text)
}
}
let beetsQuestion = SurveyQuestionA(text: "How about beets")
beetsQuestion.response = "I alse like beets. (But not with cheese)"
// 在初始化之前 text 的值為空, 初始化時 我們給一個 常量值賦值了
//--------- 默認的初始化方法----------
// swift 為 類和結構體提供了默認的初始化方法
// 這時候 屬性都需要設置默認值.
class ShoppingListItem:NSObject{
var name: String? //默認值 是 nil
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()
//------- 結構體類型的逐個初始化---------
//如果結構體沒有自定義初始化方法
// 結構體可以逐個給屬性賦值的方法初始化
struct Size{
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
//---------- 值類型 的多個初始化方法委托調用 -------
// 值類型的 初始化委托調用比較簡單, 直接在需要的地方 調用 self.init 就可
// 類 類型 是可以繼承的, 所有他的委托調用畢竟復雜
// 也可以把 委托調用的 初始化方法 寫到 擴展 Extension 中 (后面Extension 內容 中 會提到)
struct SizeA{
var width = 0.0, height = 0.0
}
struct Point{
var x = 0.0, y = 0.0
}
struct Rect{
var origin = Point()
var size = SizeA()
init(){}
init(origin: Point, size: SizeA){
self.origin = origin
self.size = size
}
init(center: Point, size: SizeA){
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
// 委托調用
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
let basicRect = Rect()
// basicRect 的 origin 是 (0.0, 0.0) size is (0.0, 0.0)
let originRect = Rect(origin: Point(x: 2.0, y:2.0), size: SizeA(width: 5.0, height:5.0))
// originRect 的 origin = (2.0, 2.0) size = (5.0, 5.0)
let centerRect = Rect(center: Point(x: 4.0, y:4.0), size: SizeA(width: 3.0, height: 3.0))
// centerRect's origin = (2.5, 2.5) size = (3.0, 3.0)
// ---------------類 繼承 和 初始化 ----------
// 類的所有存儲屬性, 包括從父類哪里繼承來的屬性,在初始時都要一個初始值
// swfit 有兩種方法給存儲屬性設置設置初始值.
// 1. 指定初始化
// 2. 便捷初始化
// -----------指定初始化 和 便捷 初始化 --------
//http://swifter.tips/init-keywords/
// Designated 指定初始化時最常用,最主要的初始化方法, 初始化過程中 會給所有存儲屬性一個初始化值
// 任何類至少有一個 Designated 指定初始化方法
//
// Convenience 便捷初始化是二等初始化方法
// 他必須在內部調用一個 Designated 指定初始化方法.
// 可以給一些屬性設置默認值,可以給一些屬性設置初始值
// 便捷初始化 可有可無
//
// 指定初始化
//init(parameters){
// statements
//}
// 便捷初始化
// convenience init(parameters){
// statements
//}
// ---------- 類 的初始化 委托------------
// 3 個準則
// 1. Designated 初始化方法 必須調用一個自己直接父類的 Designated 初始化方法
// 2. Convenience 初始化 方法 必須調用另外一個 該類的初始化方法(Convenience 或者 Designated)
// 3. Convenience 最終還是要調用一個 Designated 初始化方法
// designate 可以向上調用父類的designate
// Conveninece 只能調用該類的 初始化方法.
//---------- 類 初始化的兩個階段----------------
// 第一階段, 給所有存儲屬性一個初始值
// 第二階段, 在類初始化為實類之前對初始值進行改造
// 和 oc 初始化不同, oc 初始化時, 所有的屬性都是 nil
// 初始化 編譯的過程的四個安全檢查
// 1. 在調用父類初始化之前 必須給子類特有的屬性設置初始值, 只有在類的所有存儲屬性狀態都明確后, 這個對象才能被初始化
// 2. 先調用父類的初始化方法, 再 給從父類那繼承來的屬性初始化值, 不然這些屬性值 會被父類的初始化方法覆蓋
// 3. convenience 必須先調用 designated 初始化方法, 再 給屬性初始值. 不然設置的屬性初始值會被 designated 初始化方法覆蓋
// 4. 在第一階段完成之前, 不能調用實類方法, 不能讀取屬性值, 不能引用self
// 第一階段:
// - designated 或者 convenience 初始化方法被調用
// - 實類的內存被分配, 這時內存還沒有完全被初始化
// - 類的 designated 初始化方法確保所有的存儲屬性有了初始值, 保存這些存儲屬性的內存被初始化
// - 初始化方法傳遞給父類, 由父類完成上面的過程, 存儲所有存儲屬性值
// - 繼續向繼承鏈的上部傳遞,直到最頂層
// - 一直到最頂層的類的所有存儲屬性都被設置了初始值, 說明這個類的內存初四哈哈完成. 整個初始化的第一階段結束
// 第二階段
// - 從繼承鏈頂部到底部, 每個 designated 初始化方法都可以 引用 self, 修改屬性值, 調用實類方法.等
// - 最后 任何 convenience 初始化方法中都可以 定制實類, 引用 self
// --------------- 初始化的繼承和重寫 ------------
//http://www.cnblogs.com/Rinpe/p/5189111.html
/*
構造器的繼承:
Swift的子類不會自動繼承父類的構造器, 若繼承, 則滿足如下規則:
1.如果子類沒有提供任何指定構造器, 那么它將自動繼承父類的所有指定構造器
2.如果子類實現了父類所有的指定構造器, 無論如何實現的, 都將自動繼承父類的所有便利構造器
*/
/*
構造器的重寫:
1.子類構造器重寫了父類的指定構造器, 必須添加override修飾符
2.子類中定義的構造器只是和父類中便利構造器的形參列表, 外部形參名相同, 不算重寫
*/
/*
總結:
1.如果一個子類沒有定義任何構造器, 那么它將自動繼承父類中的所有構造器
2.如果一個子類重寫父類的所有指定構造器, 那么它將自動繼承父類中的所有便利構造器
3.如果一個子類中任意的構造器和父類的便利構造器一模一樣, 不算重寫, 創建對象的時候也只會顯示子類定義的構造器
*/
// 注意: 即使你重寫的是父類的 designated 構造器, 子類也可以寫作 convenience 構造器, 即: designated 可以重寫為 convenience
// convenience 構造器 不能被重寫
class Vehicle{
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheels"
}
}
let vehicle = Vehicle()
print("Vehicle: \(vehicle.description)")
//Vehicle: 0 wheels
class Bicycle: Vehicle{
override init() {
super.init()
numberOfWheels = 2
}
}
let bicycle = Bicycle()
print("Bicycle: \(bicycle.description)")
//Bicycle: 2 wheels
// 子類可以修改 繼承來的變量屬性, 不能修改常量屬性
//-----------構造器自定繼承----------
// swift 默認不繼承 構造器
// 當子類 1 個構造器也沒有時, 會自動繼承父類所有的構造器
// 規則1: 當子類沒有定義任何構造器, 子類自動繼承父類所有designated 構造器
// 規則2: 當子類實現了父類所有的designated 構造器方法,無論是像規則1那樣從父類繼承的,還是自定義實現的, 都會自動繼承父類所有的 convenience 構造器
// 關于構造器的實例
class Food{
var name: String
init(name: String){
self.name = name
}
convenience init(){
self.init(name: "[Unnamed]")
}
}
let namedMeat = Food(name:"Bacon")
// namedMeat.name = "Bacon"
let mysteryMeat = Food()
// mysteryMeat.name = "[Unnamed]"
class RecipeIngRedient: Food{
var quantity: Int
init(name: String, quantity: Int){
self.quantity = quantity
super.init(name: name)
}
// 這里其實是重寫了 父類的 designated 構造器 init(name:String)
convenience override init(name: String) {
self.init(name: name, quantity: 1)
}
}
let oneMysteryItem = RecipeIngRedient()
let oneBacon = RecipeIngRedient(name: "Bacon")
let sixEggs = RecipeIngRedient(name: "Eggs", quantity: 6)
class ShoppingListItemA: RecipeIngRedient{
var purchased = false
var description: String{
var output = "\(quantity) x \(name)"
output += purchased ? "?" : "?"
return output
}
}
var breakfastList = [
ShoppingListItemA(),
ShoppingListItemA(name: "Bacon"),
ShoppingListItemA(name: "Eggs", quantity: 6),
]
breakfastList[0].name = "Orange juice"
breakfastList[0].purchased = true
for item in breakfastList{
print(item.description)
/*
1 x Orange juice?
1 x Bacon?
6 x Eggs?
*/
}
// --------------- 構造器失敗 -------------
// 類, 結構體, 枚舉型 都可以初始化失敗. 有可能是非法的參數值, 或者其他條件的缺失
// 構造器失敗可以寫作 init? 失敗時 用return nil 返回
struct AnimalAA{
let species: String
init?(species: String){
if species.isEmpty{return nil}//構造器失敗 返回nil
self.species = species //構造器成功不需要 return
}
}
let someCreature = AnimalAA(species: "Giraffe")
// someCreature is of type Animal? not Animal
if let giraffe = someCreature{
print("An animal was initialized with a species of \(giraffe.species)")
// Prints "An animal was initialized with a species of Giraffe
}
let annonymousCreature = AnimalAA(species: "")
// annoymousCreature is of type Animal ? , not Animal
if annonymousCreature == nil{
print("The annonymous creature could not be initialized")
// Prints "The anonymous creature could not be initialized
}
//------------- 枚舉 構造器失敗 -------------
// 當構造枚舉的 key 不匹配任何一個 case 時 我們可以定義這枚舉類型失敗
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("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."
let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil{
print("This is not a defined temperature unit, so initialization failed.")
}
// Prints "This is not a defined temperature unit, so initialization failed.”
//-------------- 用原始值構造枚舉失敗 -----------
enum TemperatureUnitA: Character{
case kelvin = "K", celsius = "C", fahrenheit = "F"
}
let fahrenheitUnitA = TemperatureUnitA(rawValue: "F")
if fahrenheitUnitA != nil{
print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded.”
let unknownUnitB = TemperatureUnitA(rawValue: "X")
if unknownUnitB == nil {
print("This is not a defined temperature unit , so initialization failed.")
}
// Prints "This is not a defined temperature unit, so initialization failed."
//-------------- 構造器失敗傳播---------
class Product{
let name :String
init?(name: String){
if name.isEmpty { return nil }
self.name = name
}
}
class CartItem: Product{
let quantity: Int
init?(name: String, quantity: Int){
if quantity < 1 { return nil }
self.quantity = quantity
super.init(name: name)
}
}
// 用合法的 quantity 創建構造器
if let twoSocks = CartItem(name: "sock", quantity: 2){
print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
}
// Print "Item: sock, quantity: 2"
//使用非法的 quantity 創建構造器
if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)")
} else {
print("Unable to initialize zero shirts")
}
//Print "Unable to initialize zero shirts"
// 使用非法的 name 創建構造器, 父類構造器失敗,導致該類構造器失敗
if let oneUnnamed = CartItem(name: "", quantity: 1) {
print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)")
} else {
print("Unable to initialize zero shirts")
}
//Prints "Unable to initialize zero shirts"
//------------ 重寫構造器失敗 ------------
// 當父類是可以失敗的構造器時
// 如何確保子類的構造器一定是成功的呢!
// 只要子類不滿足造成父類構造器失敗的條件即可
class Document{
var name: String?
// name 可選值, 可為 nil
init(){}
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
class AutomaticallyNamedDocument: Document{
override init() {
super.init()
self.name = "[Untitled]"
}
override init(name: String){
// 沒有調用會讓父類構造器失敗的 方法 `init(name: String)`
super.init()
if name.isEmpty {
// 給 name 一個默認值,
self.name = "[Untitled]"
} else {
self.name = name
}
}
}
class UntitledDocument: Document{
override init() {
// 如果這里寫作 super.init(name: "") 編譯器回報錯, 因為這樣寫沒意義
super.init(name: "[Untitled]")!// 強制解包
}
}
// ------- 父類構造器可能失敗,子類構造器一定成功 init!-----
// 當使用 init! 時, 必須確定該類一定有值, 如果該類為 nil 則會拋出異常
// --------- 要求實現的構造器 ------------
// 用關鍵字 required 修飾的構造器是子類必須重寫的的構造器
// 重寫 required 的構造器 不需要 override 關鍵字
class SomeClass {
required init() {
}
}
class SomeSubclass: SomeClass{
//重寫父類構造器 沒有 override
required init() {
//
}
}
// ---------- 用 閉包 和 方法 給屬性設置默認值
// class SomeClassA {
//
// let someProperty: Sometype = {
// // create a default value for someProperty inside this closure
// // someValue must be of the same type as SomeType”
//
// return someValue
// }()
//
// }
// 上面的代碼, 屬性 someProperty 默認值是閉包的返回值.
// 如果沒有最后 的小括號() 屬性 someProperty 的 值 是一個閉包(不是返回值)
// 小括號還有一個作用, 讓閉包立即運行, 返回結果
struct Chessboard {
let boardColors: [Bool] = {
var temporaryBoard = [Bool]()
var isBlack = false
for i in 1...8 {
for j in 1...8 {
temporaryBoard.append(isBlack)
isBlack = !isBlack
}
isBlack = !isBlack
}
return temporaryBoard
}()
func squareIsBlackAt(row: Int, column: Int) -> Bool{
return boardColors[(row * 8) + column]
}
}
let board = Chessboard()
print(board.squareIsBlackAt(row: 0, column: 1))
//true
print(board.squareIsBlackAt(row: 7, column: 7))
//false
Swift - 構造器
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
推薦閱讀更多精彩內容
- 這段時間用Swift寫項目時候便發現它的構造函數相比OC真的是復雜了許多,加了很多的限制和條件,不過這么設計...