Swift中enum、struct、class三者異同
前言
由于在開發過程中常常需要用到系統提供的基礎類型之外的的類型,所以Swift允許我們根據自己的需要構建屬于自己的類型系統以便于更加靈活和方便的開發程序并將其稱之為 named types 。Swift主要為我們提供了以下四種 named types 分別是: enum 、 struct 、 class 和 protocol , 相信熟悉objective-c開發的同學們對于iOS中枚舉、結構體和類的概念一點都不陌生。相比于前輩objective-c中的這三者,Swift將 enum 和 struct 變得更加靈活且強大,并且賦予了他們很多和 class 相同的屬性實現更加豐富多彩的功能,以至于有時候我們很難分清他們到底有什么區別以及我該什么時候用哪種類型,接下來本文將重點介紹一下在Swift中 enum 和 struct 的定義和新特性以及兩者與 class 之間的異同,也是自己學習Swift以來的階段性總結
枚舉(enum)
- 枚舉的定義 :
Swift中的枚舉是為一組有限種可能性的相關值提供的通用類型(在C/C++/C#中,枚舉是一個被命名的整型常數的集合);使用枚舉可以類型安全并且有提示性地操作這些值。與結構體、類相似,使用關鍵詞 enum 來定義枚舉,并在一對大括號內定義具體內容包括使用 case 關鍵字列舉成員。就像下面一樣://定義一個表示學生類型的全新枚舉類型 StudentType,他有三個成員分別是pupil(小學生,玩LOL最怕遇到這種隊友了)、middleSchoolStudent(中學生,現在的中學生都很拽)、collegeStudents(大學生,據說大學生活很不錯,注意斷句) enum StudentType { case pupil case middleSchoolStudent case collegeStudent }
枚舉中有兩個很容易混淆的概念: 原始值(raw value) 、 關聯值(associated value) ,兩個詞聽起來比較模糊,下面簡單介紹一下: - 枚舉的原始值(raw value)
枚舉成員可以用 相同類型的默認值預先填充 ,這樣的值我們稱為 原始值(raw value) ,下面的 StudentType 中三個成員分別被 Int 類型的 10 、 15 、 20 填充表示不同階段學生的年齡。注意: Int 修飾的是 StudentType 成員原始值的類型而不是 StudentType 的類型, StudentType 類型從定義開始就是一個全新的枚舉類型。enum StudentType: Int{ case pupil = 10 case middleSchoolStudent = 15 case collegeStudents = 20 }
// 常量student1值是 10 let student1 = StudentType.pupil.rawValue // 變量student2值是 15 var student2 = StudentType.middleSchoolStudent.rawValue // 使用成員rawValue屬性創建一個`StudentType`枚舉的新實例 let student3 = StudentType.init(rawValue: 15) // student3的值是 Optional<Senson>.Type type(of: student3) // student4的值是nil,因為并不能通過整數30得到一個StudentType實例的值 let student4 = StudentType.init(rawValue: 30)
總結一句: 原始值是為枚舉的成員們綁定了一組類型必須相同值不同的固定的值(可能是整型,浮點型,字符類型等等)。 這樣很好解釋為什么提供原始值的時候用的是等號。 - 枚舉的關聯值(associated value)
關聯值 和 原始值 不同, 關聯值更像是為枚舉的成員們綁定了一組類型,不同的成員可以是不同的類型 (提供關聯值時用的是括號)。例如下面的代碼://定義一個表示學生類型的枚舉類型 StudentType,他有三個成員分別是pupil、middleSchoolStudent、collegeStudents enum StudentType { case pupil(String) case middleSchoolStudent(Int, String) case collegeStudents(Int, String) }
//student1 是一個StudentType類型的常量,其值為pupil(小學生),特征是"have fun"(總是在玩耍) let student1 = StudentType.pupil("have fun") //student2 是一個StudentType類型的常量,其值為middleSchoolStudent(中學生),特征是 7, "always study"(一周7天總是在學習) let student2 = StudentType.middleSchoolStudent(7, "always study") //student3 是一個StudentType類型的常量,其值為collegeStudent(大學生),特征是 7, "always LOL"(一周7天總是在擼啊擼) let student3 = StudentType.middleSchoolStudent(7, "always LOL")
switch student3 { case .pupil(let things): print("is a pupil and \(things)") case .middleSchoolStudent(let day, let things): print("is a middleSchoolStudent and \(day) days \(things)") case .collegeStudent(let day, let things): print("is a collegeStudent and \(day) days \(things)") }
- 遞歸枚舉
遞歸枚舉是擁有另一個枚舉作為枚舉成員關聯值的枚舉(引自文檔翻譯)。
關于 遞歸枚舉 我們可以拆封成兩個概念來看: 遞歸 + 枚舉 。 遞歸 是指在程序運行中函數(或方法)直接或間接調用自己的這樣一種方式,其特點為重復有限個步驟、格式較為簡單。下面是一個經典的通過遞歸算法求解 n! (階乘)的函數。func factorial(n: Int)->Int { if n > 0 { return n * factorial(n: n - 1) } else { return 1 } } //1 * 2 * 3 * 4 * 5 * 6 = 720 let sum = factorial(n: 6)
結構體(struct)
- 結構體的定義 :
結構體是由一系列具有相同類型或不同類型的數據構成的數據集合。結構體是一種值類型的數據結構,在Swift中常常使用結構體封裝一些屬性甚至是方法來組成新的復雜類型,目的是簡化運算。我們通過使用關鍵詞 struct 來定義結構體。并在一對大括號內定義具體內容包括他的成員和自定義的方法(是的,Swift中的結構體有方法了),定義好的結構體存在一個自動生成的成員初始化器,使用它來初始化結構體實例的成員屬性。廢話不多說直接上代碼://定義一個 Student(學生)類型的結構體用于表示一個學生,Student的成員分別是語、數、外三科`Int`類型的成績 struct Student { var chinese: Int var math: Int var english: Int }
- 結構體實例的創建 :
創建結構體和類的實例的語法非常相似,結構體和類兩者都能使用初始化器語法來生成新的實例。最簡單的語法是在類或結構體名字后面接一個空的圓括號,例如 let student1 = Student() 。這樣就創建了一個新的類或者結構體的實例,任何成員都被初始化為它們的默認值(前提是成員均有默認值)。但是結合上面的代碼,由于在定義 Student 結構體時我們并沒有為他的成員賦初值,所以 let student1 = Student() 在編譯器中報錯了,此處報錯并不是因為不能這樣創建實例而是因為 student1 成員沒有默認值,所以我們可以使用下面的方式創建實例://使用Student類型的結構體創建Student類型的實例(變量或常量)并初始化三個成員(這個學生的成績會不會太好了點) let student2 = Student(chinese: 90, math: 80, english: 70)
struct Student { var chinese: Int = 50 var math: Int = 50 var english: Int = 50 } let student2 = Student(chinese: 90, math: 80, english: 70) let student4 = Student()
- 自定義的初始化器
當我們想要使用自己的方式去初始化創建一個 Student 類型的實例時,系統提供的成員初始化器可能就不夠用了。例如,我們希望通過形如: let student5 = Student(stringScore: "70,80,90") 的方式創建實例時,就需要自定義初始化方法了:struct Student { var chinese: Int = 50 var math: Int = 50 var english: Int = 50 init() {} init(chinese: Int, math: Int, english: Int) { self.chinese = chinese self.math = math self.english = english } init(stringScore: String) { let cme = stringScore.characters.split(separator: ",") chinese = Int(atoi(String(cme.first!))) math = Int(atoi(String(cme[1]))) english = Int(atoi(String(cme.last!))) } } let student6 = Student() let student7 = Student(chinese: 90, math: 80, english: 70) let student8 = Student(stringScore: "70,80,90")
- 定義其他方法
如果此時需要修改某個學生某科的成績,該如何實現呢?當然,我們可以定義下面的方法://更改某個學生某門學科的成績 func changeChinese(num: Int, student: inout Student){ student.chinese += num } changeChinese(num: 20, student: &student7)
struct Student { var chinese: Int = 50 var math: Int = 50 var english: Int = 50 //修改數學成績 mutating func changeMath(num: Int) { self.math += num } } var student7 = Student(chinese: 20, math: 30, english: 40) //更改分數中語文學科的成績 func changeChinese(num: Int, student: inout Student){ student.chinese += num } changeChinese(num: 20, student: &student7) student7.changeMath(num: 10)
- 常見的結構體
Swift中很多的基礎數據類型都是結構體類型,下面列舉的是一些常用的結構體類型://表示數值類型的結構體: Int,Float,Double,CGFloat... //表示字符和字符串類型的結構體 Character,String... //位置和尺寸的結構體 CGPoint,CGSize... //集合類型結構體 Array,Set,Dictionary...
// Person 類 class Person { var name: String = "jack" let life: Int = 1 } var s1 = Person() var s2 = s1 s2.name = "mike" s1
// People 結構體數據結構 struct People { var name: String = "jack" let life: Int = 1 } var p1 = People() var p2 = p1 p2.name = "mike" p1
總結
上面關于 枚舉 、 結構體 的介紹僅僅是冰山一角,了解這些基礎內容,可以幫助我們在Swift開發中更熟練的使用他們。這里象征性的做一下總結: - 枚舉、結構體、類的共同點:
1,定義屬性和方法;
2,下標語法訪問值;
3,初始化器;
4,支持擴展增加功能;
5,可以遵循協議; - 類特有的功能:
1,繼承;
2,允許類型轉換;
3,析構方法釋放資源;
4,引用計數; - 類是引用類型
引用類型(reference types,通常是類)被復制的時候其實復制的是一份引用,兩份引用指向同一個對象。所以在修改一個實例的數據時副本的數據也被修改了( s1 、 s2 )。 - 枚舉,結構體是值類型
值類型(value types)的每一個實例都有一份屬于自己的數據,在復制時修改一個實例的數據并不影響副本的數據( p1 、 p2 )。 值類型 和 引用類型 是這三兄弟最本質的區別。
以上就是本人前段時間學習心得,示例代碼在Swift3.0語法下都是編譯通過的,知識點比較少,部分描述引自官方的文檔。如果文中有任何紕漏或錯誤歡迎在評論區留言指出,本人將在第一時間修改過來;喜歡我的文章,可以關注我以此促進交流學習,謝謝支持。
來自:http://www.jianshu.com/p/78a6a4941516
本文由用戶 xtceetg 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!