Swift具體解釋之六----------------枚舉、結構體、類
枚舉、結構體、類
註:本文為作者自己總結。過於基礎的就不再贅述 ,都是親自測試的結果。如有錯誤或者遺漏的地方。歡迎指正,一起學習。
1、枚舉
枚舉是用來定義一組通用類型的一組相關值 ,關鍵字enum
,case
關鍵詞表明新的一行成員值將被定義。
enum Direction{
case East
case West
case South
case North
}
這裏定義了一個簡單的枚舉類型 , 裏面有四個枚舉元素 。
也能夠用一行的形式
enum Direction{
case East , West , South , North
}
能夠這樣來訪問這個枚舉類型var dir = Direction.East
。這時候這個變量 dir
已經被判斷成Direction
,又一次賦值的時候 能夠直接用短語法dir = .West
。
- 相關值(Associated Values)
你能夠定義 Swift 的枚舉存儲不論什麽類型的相關值,假設須要的話,每一個成員的數據類型能夠是各不同樣的。
enum Barcode {
case UPCA(Int , Int , Int ,Int )
case QRCode(String)
}
你能夠這樣給它賦值var pro = Barcode.UPCA(8, 53627, 29009, 1)
。也能夠這樣改動pro = .QRCode("DSLEKWLJELJAIWFLWKJF")
這樣取值
switch pro{
case .UPCA(let a1,let a2, let a3, let a4):
print("\(a1) , \(a2) , \(a3) , \(a4)")
case .QRCode(let s):
print(s)
}
你也能夠把let寫在最前面
switch pro{
case let .UPCA( a1, a2, a3, a4):
print ("\(a1) , \(a2) , \(a3) , \(a4)")
case let .QRCode(s):
print(s)
}
兩個得到同樣的結果 : DSLEKWLJELJAIWFLWKJF
- 給枚舉指定特定類型 (原始值)
你能夠給一個枚舉指定類型 。比方說String 類型 。
enum SignBuilding : String{
case Beijing = "天安門"
case XiAn = "兵馬俑"
}
這裏將 這個枚舉定義成 字符串類型的 。
通過這樣能夠取到相應的值print(SignBuilding.Beijing.rawValue)
也能夠原始值隱式賦值
enum IntVal:Int {
case Val1 = 1 , Val2 , Val3
}
假設沒給Val1賦值 。默認是 0 。遞增是 1 ,也能夠 自己制定初始值 (這裏我們給定了初始值1)
也能夠使用原始值來初始化枚舉 let val = IntVal(rawValue: 2)
print(val) //Optional(IntVal.Val2)
,這裏得到的結果是Optional類型 ,由於不是全部的數字都能匹配到相應的枚舉類型 。如 :let errorVal = IntVal(rawValue: 5)
print(errorVal) //nil
官方還給出了遞歸枚舉 ,關鍵字 indirect
。可是我這邊嘗試了好多次 ,這個關鍵字也沒有變色 ,還會報錯 。
enum Calculate{
case Num(Int)
indirect case Plus(Calculate,Calculate)
indirect case ChenFa(Calculate,Calculate)
}
在網上搜了下 , 由於是2.0的新特性 。網上也沒有太多的解釋。大家能夠研究下 。我也研究下 ,研究出來再來補上。
枚舉裏面還能夠有方法 ,只是不太推薦把 。全然能夠用結構體和方法 。
枚舉和結構體都是值類型 。在傳遞的時候都是以拷貝的方式。
類是引用類型 ,傳遞的時候僅僅是傳遞一個引用 。
2、類和結構體
類 Class
結構體 struct
簡單的定義
struct myPoint
{
var x = 0;
var y = 0;
}
class Person {
var name:String?;
var age:Int?;
var p1 = myPoint(x: 1,y: 2);
var p = myPoint();
}
這裏定義了一個簡單的結構體和類,類中定義了幾個簡單的屬性 , 包含 一個結構體屬性 ,給出了兩種初始化的方法 。關於屬性的聲明能夠去看 Swift具體解釋之中的一個 ——– 變量聲明 。
Int , float 。 數組 字典 等 都是值類型 後臺都以結構體的方式實現
一般使用結構體的情況
- 結構體的主要目的是用來封裝少量 簡單的數據值
- 估計實例在賦值或傳遞過程中將會被拷貝 而不是引用
- 不論什麽在結構體中存儲的值類型屬性也將被拷貝 而不是引用
- 不須要繼承已存在的類型 或者屬性 行為(結構體是沒有繼承的)
假設創建了一個結構體的實例。而且將這個實例賦值給一個常量 則無法改動其屬性 。就算是變量屬性也無法改動
let p1 = myPoint(x: 1,y: 1)
這裏我嘗試改動結構體中的變量x 報錯 。
引用類型賦給常量,仍然能夠改變其變量屬性。所以類的實例能夠賦值給一個常量
- 懶載入
延遲存儲屬性是指當第一次被調用的時候才會計算其初始值的屬性。
在屬性聲明前使用lazy來標示一個延遲存儲屬性。 (懶載入)
註意:必須將延遲存儲屬性聲明成變量(使用var關鍵字),由於屬性的值在實例構造完畢之前可能無法得到。而常量屬性在構造過程完畢之前必須要有初始值,因此無法聲明成延遲屬性。
看下官方給的樣例。
class DataImporter {
/*
DataImporter 是一個將外部文件裏的數據導入的類。
這個類的初始化會消耗不少時間。
*/
var fileName = "data.txt"
// 這是提供數據導入功能
}
class DataManager {
lazy var importer = DataImporter() //這裏使用了懶載入 在第一次用到的時候才去創建這個實例 假設創建DataManager 就去創建DataImporter 有可能並不須要這個實例。浪費內存和時間
var data = [String]()
// 這是提供數據管理功能
}
let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// DataImporter 實例的 importer 屬性還沒有被創建
這裏能夠看到我們並沒有使用DataImporter , 所以在創建DataManager()的時候並不並不須要初始化DataImporter ,所以我們使用懶載入在這時候就節省了內存的開支。
可是。假設被標記位lazy的屬性 在沒有被初始化的時候被多個線程訪問 這時候 不能保證這個屬性僅僅被實例一次
我們能夠通過以下的方式定義一個僅僅讀屬性 。
var a = 1.2;
var b:Double{
return a*4
}
- 類型屬性
無論這個類有多少個實例 ,它的類屬性 僅僅有一個 。
關鍵字static
struct myStruct
{
static var height = 19.3
}
能夠直接通過結構體的名字或者類的名字來調用類型 屬性print(myStruct.height)
只是在類中有時候須要使用關鍵字class
,來同意它的子類重寫這個屬性 。
class myClass {
static let name = "zhangsan "
static var age = 21
static var status: Int { return 1 }
//在定義計算型屬性的時候能夠使用 關鍵字 class 來支持子類對父類進行重寫
class var canOverrid: Int { return 10 }
}
class sonClass: myClass {
override static var canOverrid: Int { return 89 }
//static let name = "zhangsan " //cannot override with a stored property ‘name‘
}
這裏我們子類能夠重寫class
標記的類型屬性 。
- 方法
方法能夠分成實例方法和類型方法 。
類、結構體、枚舉都能夠定義實例方法;實例方法為給定類型的實例封裝了具體的任務與功能。類、結構體、枚舉也能夠定義類型方法;類型方法與類型本身相關聯。
結構體和枚舉能夠定義方法 是swift和oc的一大差別
類型方法就是在func 前面加static 類有時候可能須要加class 。
跟屬性的使用方法是一樣的,這裏就不在實例 。
- 變異方法
值類型的屬性不能在實例方法中被改動。可是有時候你確實想改動過。這時候 你能夠使用變異方法 。
關鍵字 mutating
struct Counter{
var count = 0
func getCount() ->Int{
return count
}
//由於值類型的屬性不能在實例方法中被改動 這裏使用了變異方法
mutating func increment()
{
count++
}
}
var c = Counter()
print(c.count) // 0
print(c.getCount()) // 0
c.increment()
print(c.count) // 1
變異方法能夠給自己賦值
enum Level {
case High , Mid ,Low
mutating func next() {
switch self
{
case .High:
self = Mid
case .Mid:
self = Low
default:
self = High
}
}
}
var level = Level.High
level.next()
print(level) //Level.Mid
level.next()
print(level) //Level.Low
學習iOS。有他就夠了,小碼哥視頻,傳智、黑馬、各種swift書籍
Swift具體解釋之六----------------枚舉、結構體、類