類的介紹和定義
- Swift也是一門面向對象的開發語言。
- 面向對象的基礎就是類,類產生對象。
- Swift如何定義類:
- class關鍵字定義類
class 類名: SuperClass { //定義屬性和方法
}
* 使用注意:
* 定義類的時候,可以沒有父類,那么該類就是根類
* 通常情況下定義定義類時,繼承自NSObject
**如何定義類的屬性**
* Swift中類的屬性有多種:
* 存儲屬性:存儲實例的常量和變量
* 計算屬性:通過某種方式計算出來的屬性
* 類屬性:與整個類相關的屬性
* 存儲屬性
```
class person: NSObject{
//存儲屬性
var age = 0
var name: String?
}
let child = person()
child.age = 18
child.name = "小明"
if let name = child.name {
print("\(name)今年\(child.age)了")
}
//結果:小明今年18了
```
* 計算屬性
在類中聲明的計算屬性,這個屬性可以由類中定義的函數來完成,但是蘋果官方并不見這種實現方式,因為計算屬性的方式更加簡單明了,下面就來實現以下某個人的在某段時間內完成跑步的平均時速。
class person: NSObject{
var time = 2
var startSpeed = 10.0
var hightSpeed = 20.0
var endSpeed = 5.0
//推薦
var averageSpeed: Double {
return (startSpeed + hightSpeed + endSpeed) * 0.5
}
//不推薦
func averageSpeedFunction() -> Double {
return (startSpeed + hightSpeed + endSpeed) * 0.5
}
}
let child = person()
child.averageSpeedFunction()
child.averageSpeed
* 類屬性
類屬性是和整個類相關的屬性,而且是通過類名來訪問。常見于單例!
class person: NSObject{
//定義某個人有書籍的數量
static var book = 0
}
person.book = 2
//結果:2
**類的構造函數**
* 構造函數
* 構造函數類似于OC中的初始化方法:init方法
* 默認情況下創建某個類時,必然會調用一個構造函數
* 即便開發者沒有構建構造函數,編譯器也會提供默認的構造函數
* 如果繼承自NSObject可以對父類的構造函數進行重寫
* 構造函數的基本使用
* 類的屬性必須有值
* 如未在定義時初始化值,可以在構造函數中賦值,通過傳遞參數,初始化類對象。
```
class person: NSObject{
var name: String?
var height = 0.0
//重寫父類的構造方法
//如果重寫父類的構造方法,在實例化此類時,Xcode會提示這個方法,如果未重寫,Xcode只會提示,我們自定義的構造方法!
override init(){
super.init()
}
//自定義構造方法
init(name: String, height: Double) {
self.name = name
self.height = height
}
}
let child = person(name: "小明", height: 1.88)
child.name
child.height
//結果:小明 1.88
```
* 通過字典參數實例化類對象
```
class person: NSObject{
var name: String?
var height = 0.0
//重寫父類的構造方法
override init(){
super.init()
}
//自定義構造方法
init(name: String, height: Double) {
self.name = name
self.height = height
}
init(dict: [String : AnyObject]) {
//此種寫法會報錯,因為從字典中取出的值為AnyObject?可選類型,直接賦值會報錯!
//self.name = dict["name"]
//self.height = dict["height"]
//解決方法1:
//as? 轉換符 將as?左側的類型轉換成as?右側的類型的可選類型
name = dict["name"] as? String
//as! 轉換符 將as!左側的類型轉換成as! 右側的類型的可選類型
height = dict["height"] as! Double
//但是此種寫法同時有帶來了新的問題,強制解包是很危險的操作,會造成程序crash
//解決方法2:
name = dict["name"] as? String
//可選綁定
if let tempHeight = dict["height"] as? Double {
height = tempHeight
}
}
}
let child = person(dict: ["name":"小明" as AnyObject, "height": 1.90 as AnyObject])
```
利用KVC實現構造函數實現
```
class person: NSObject{
var name: String?
var height = 0.0
//重寫父類的構造方法
override init(){
super.init()
}
//自定義構造方法
init(name: String, height: Double) {
self.name = name
self.height = height
}
//KVC
init(dict: [String : AnyObject]) {
super.init()
setValuesForKeys(dict)
}
//防止傳入的字典存在未知的鍵值->報錯
override func setValue(_ value: Any?, forUndefinedKey key: String) {}
}
let child = person(dict: ["name":"小明" as AnyObject, "height": 1.90 as AnyObject, "weight": 100 as AnyObject])
child.name
child.height
//結果:小明 1.9
```
**類的屬性監聽器**
* 在OC中我們可以重寫set方法來監聽屬性的改變
* Swift中可以通過屬性觀察者來監聽和響應屬性的改變
* 通常監聽存儲屬性和類屬性
* 通過設置以下方法來定義觀察者
* willSet:將在屬性值即將改變時調用
* didSet:將在屬性值改變后調用
class person: NSObject{
var name: String?{
willSet{
print("\(name)")
}
didSet{
print("\(name)")
}
}
}
let child = person()
child.name = "小明"
**結構體的介紹和定義**
結構體與類存在很多共同點:
* 定義屬性用于存儲值
* 定義方法用于提供功能
* 定義下標操作使得可以通過下標語法來訪問實例所包含的值
* 定義構造器用于生成初始化值
* 通過擴展以增加默認實現的功能
* 實現協議以提供某種標準功能
* Swift中如何定義結構體:
* struct關鍵字定義結構體
struct 結構體名{
//結構體屬性or方法
}
**結構體實例化**
結構體實例化和類實例化非常相似:
struct SomeStruct{
//結構體屬性or方法
var width = 0
var height = 0
}
//實例化結構體
var someStruct = SomeStruct()
在Swift中,結構體可以直接修改結構體的子屬性的值,這點是與OC不同之處!
import UIKit
struct SomeStruct{
//結構體屬性or方法
var width = 0
var height = 0
}
var someStruct = SomeStruct()
someStruct.height = 100
someStruct.height
//結果:someStruct.height值為100
**結構體的逐一構造器**
結構體存在逐一構造器,而類中默認是不存在的!我們可以自定義構造函數來完成逐一構造器,上述類的自定義構造方法其實就是自定義的逐一構造器方法!
struct SomeStruct{
//結構體屬性or方法
var width = 0
var height = 0
}
var someStruct = SomeStruct(width: 66, height: 88)
someStruct.height
//結果:88
someStruct.width
//結果:66
**結構體與類之間的選擇**
?結構體總是通過值傳遞(值類型),類總是通過引用傳遞(引用類型)!
按照通用的準則,當符合一條或多條以下條件時,請考慮構建結構體:
* 該數據結構的主要目的是用來封裝少量相關簡單數據值。
* 有理由預計該數據結構的實例在被賦值或傳遞時,封裝的數據將會被拷貝而不是被引用。
* 該數據結構中儲存的值類型屬性,也應該被拷貝,而不是被引用。
* 該數據結構不需要去繼承另一個既有類型的屬性或者行為。
######注意:
在Swift中字符串、數組、字典均為結構體的形式實現(OC中均為類的形式實現)。拷貝行為看起來似乎總會發生。然而,Swift 在幕后只在絕對必要時才執行實際的拷貝。Swift 管理所有的值拷貝以確保性能最優化,所以你沒必要去回避賦值來保證性能最優化。
Zeb
參考地址:https://github.com/numbbbbb/the-swift-programming-language-in-chinese