面向對象總體概括:
Swift 不僅能夠面向過程編程,也能夠面向對象編程(OOP)。面向對象其實就是“以對象為核心”,把我們的客觀世界想着是由一個個對象組成的,面向對象編程則為對象提供了屬性和方法,屬性就是為了描述對象的一些狀態,方法則是告訴你對象該做什么。面向對象和核心就是“類”和“對象”!在我剛接觸編程的時候,其實我也很容易把這東西混淆了,你要也是剛接觸編程,能幫到你的,我覺得反而是時間。你要實在是有點難理解,就別去鑽牛角尖,也許明天因為某個東西你就會恍然大悟。超喜歡那種感覺!
面向對象的三大特性: 繼承 多態 封裝 (封裝和繼承好理解,多態我在前面的博客中有提過,不理解可以往前面翻翻去看一下)。
Swift 面向對象編程的有五個單元: 枚舉 結構體 類 擴展 協議
從整體的一個功能上看Swift的 枚舉、結構體、類 三者具有完全平等的地位。(在后面我們會對這三者進行一個區分的)其他的面向對象編程的語言中都蛀牙提供了類一種單元,而Swift則有三種,大家想想,OC、Java等語言是面向對象編程的,Swift 是面向對象和過程都可以,Swift 是一門全新的語言,它才面世幾年,而OC都快三十年了。所以Swift不簡單,要是Swift剛出來那時候有人寫出一個 println("Hello World")(2.0之前的寫法) 就覺得它很簡單,你真的就錯了。Swift 不簡單,你說簡單估計是因為你也只研究到 print("Hello World"),哈哈......
在Swift中,枚舉和結構體是值類型的,類是引用類型。值類型和引用類型的區別,我們后面說,先知道這一點。
在Swift的類、結構體、枚舉中都可以定義(屬性、方法、下標、構造體、嵌套類型),下面我們一個一個的用我小小的認識說一下它們,我也會給大家一些我看到的很不錯的博客鏈接,方便大家更好的掌握,理解Swift。
一:枚舉
Swift枚舉是用來管理一組值的,當然也是有限的。比如一年四季你可以用枚舉來管理,寫個季節枚舉,里面的值就是(春夏秋冬),還有性別(男女),再到我們的項目中比如經常看到的在即時通訊里面的消息類型(文字,圖片,語音,系統消息)等等。比如下面的例子:
給大家看看我們在OC中是怎么定義枚舉的,大家對比着理解:
/** 發送的消息類型 */ enum ZxMessageType: Int { case MessageTypeUnknown = 0 // 未知 case MessageTypeSystem // 系統 case MessageTypeText // 文字 case MessageTypeImage // 圖片 case MessageTypeVoice // 語音 case MessageTypeVideo // 視頻 case MessageTypeFile // 文件 case MessageTypeLocation // 位置 case MessageTypeShake // 抖動 }
// OC 枚舉
/** * 消息類型 */ typedef NS_ENUM(NSInteger, TLMessageType){ MessageTypeUnknown, // 未知 MessageTypeSystem, // 系統 MessageTypeText, // 文字 MessageTypeImage, // 圖片 MessageTypeVoice, // 語音 MessageTypeVideo, // 視頻 MessageTypeFile, // 文件 MessageTypeLocation, // 位置 MessageTypeShake, // 抖動 };
順便給大家提一下,上面這兩種方式,是我自己的習慣,其實按照我們最開始學的時候的方式去定義沒問題,只是在官方的定義中,OC和Swift都是上面例子的方式寫枚舉,這樣寫也有好處,有同行分析過了,鏈接這里。
Swift枚舉和 C,OC 枚舉的區別: Swift的枚舉成員不會被分配一個默認的整數值,它的枚舉名本身就是一個枚舉實例和整數值之間可沒有任何的關系。
Swift的知識點還有:枚舉值和Switch語句 原始值 關聯值 等幾個方面,但我就不說了,說了也不會有前輩們總結的詳細,我把知識點鏈接給大家,里面的內容足夠掌握 Swift的枚舉了!
二:類和結構體
把這兩個放在一起,純粹是因為這兩個太像了,我們先把區別羅列出來,剩下的兩者都一樣。
1: 結構體是值類型,類是引用類型。
2: 結構體不支持繼承,不支持類型轉換。(值類型原因)
3: 結構體不支持定義析構器。 (后面提析構器的時候說)
插入說個問題: 實例 和 對象 的問題,在以前的OC中,對象就是實例,實例就是對象。但在Swift 中,以前記得看書的時候說是有 類 的實例才能叫做 對象,而 結構體 和 枚舉 的實例只能叫做實例,不能叫做對象。我覺得應該是和它們之間的類型有關系,他們之間最主要的區別其實也都是圍繞着 值類型和引用類型展開的。
看看類的定義:
class name: super class { // code // 構造器 // 屬性 // 方法 // 下標 }
注意點:
1: 當我們自己不為結構體/類 提供構造器時,系統為結構體生成兩個構造器,一個是無參數的構造器,一個初始化所有存儲屬性的構造器。如果希望用戶定義的構造器與系統提供的構造器同時存在,則不能直接在類中定義構造器,可用擴展來添加。
2: Swift 的屬性分為兩類,存儲屬性 和 計算屬性 ,存儲屬性類似於OC中的實例變量,它用來保存類型本身或者實例變量的狀態數據。計算屬性相當於OC中用setter和getter合成的 property 屬性,它並不一定保存數據。
三:存儲和計算屬性
(一) 存儲屬性
Swift 定義存儲屬性的方法和定義它變量常量的方法相同,我們就不累贅。
存儲屬性可以分為 實例存儲屬性 類型存儲屬性 兩類。這個可以參考OC的實例方法和類型方法,實例變量和類型變量一樣的道理去理解。
注意點:
1 : 枚舉不能定義 實例存儲屬性, 類和結構體可以。
2 : Swift 要求所有的存儲屬性都必須顯式的制定初始值,要么你在定義的時候指定初始值,要么你在構造器里面指定初始值。
3 : 如果將存儲屬性的類型申明為可選類型,系統就可以將這些屬性的初始值設置為 nil (大家一定注意,Swift的nil和OC的nil完全不一樣,Swift的nil是一個確定的值,叫缺失值,而OC的nil是一個不指向任何類型的指針)。
比如定義的一個 model;
class ZxUser: NSObject { var username:String = "" var userID:String = "" var nikename:String = "" var avatarURL:String = "" var motto:String = "" var phoneNumber:String = "" var pinyin:String = "" var initial:String = "" }
在存儲屬性里面,我們要注意的是這個,延遲存儲屬性,延遲存儲屬性是指在第一次調用時才會被計算初始值的屬性,聲明延遲存儲屬性需要使用 Lazy 修飾符。
我們OC里面常用到的懶加載就是延時存儲屬性,我們看一個具體的例子就明白了:比如我們懶加載這個 ZxMessageModel 類型的數組,寫法如下:
lazy var dataArray: Array<ZxMessageModel> = { // 弱引用防止循環引用寫法 // [weak self] in // [unowned self] in // __weak typeof (self) Wself = self let dataArray:Array = Array<ZxMessageModel>() return dataArray }()
至於懶加載為什么這樣寫,有什么好處,看下面的鏈接!
Swift 懶加載(lazy) 和 Objective-C 懶加載的區別
(二) 計算屬性
計算屬性只能定義成變量形式,也就只能用 var 修飾。
計算屬性就是相當於我們 OC 和 JAVA中通過 setter 和 getter 合成的屬性(property屬性)是一樣的。
我們在OC中經常會這樣用一個 property 屬性,在.h中聲明了這個屬性,在.m中我們寫它的 set 或者 get 方法,然后在他們的 set 或者 get 方法里面做一些操作,看下面的這個例子:
// 依據不同的條件判斷返回不同的值 var cellHeight:CGFloat{ get{ switch self.messageType! { case ZxMessageType(rawValue:2)!: return self.messageSize.height + 40 > 60 ? self.messageSize.height + 40 :60 case ZxMessageType(rawValue:3)!: return self.messageSize.height + 20; default: break } return 0 } }
// 依據不同的消息類型設置不同的 cellIndentify var messageType:ZxMessageType?{ get{ return self.messageType } set { switch messageType! { case ZxMessageType(rawValue:2)!: self.cellIndentify = "TextMessageCell"; case ZxMessageType(rawValue:3)!: self.cellIndentify = "ImageMessageCell"; case ZxMessageType(rawValue:4)!: self.cellIndentify = "VoiceMessageCell"; case ZxMessageType(rawValue:5)!: self.cellIndentify = "SystemMessageCell"; default: break } } }
學習鏈接:
四:屬性觀察者
willSet(newValue): 被觀察的屬性即將被賦值之前自動調用該方法。
didSet(oldValue): 被觀察的屬性被賦值完成之后自動調用該方法。
上面的形參名是Swift隱式為它們提供的,你可以在方法中直接調用,扣上面字眼去理解它們的定義和使用;
var nameString = ""{ willSet{
print("set value") } didSet{
print("did set value") } }
五:方法
方法這里我們就說一點,這個感覺是很基礎的了,函數方法,說多了也沒意思。
使用static 或者 class 修飾的方法屬於該類型的類方法,是可以使用該類型本身來調用。class 一般是在類里面修飾, static 一般用在結構體和枚舉中修飾。
六:下標
所有的Swift 類型(結構體、枚舉、類)都支持定義下標,下標可以作為訪問對象,集合或者序列的簡化方式。
Swift使用 subscript 關鍵字定義下標。
看下面這個例子就明白它的作用了:
struct TimesTable { let multiplier: Int subscript(index: Int) ->Int { return multiplier * index } } // 在另外的方法里面這樣調用,看輸出的結果 let threeTimesTable = TimesTable(multiplier: 3) print("sixtimes three is \(threeTimesTable[6])") // prints"six times three is 18"
七:可選鏈
Swit 的所有類型默認是不能接受nil值的,如果程序想讓某種數據類型能夠接受nil值,則要將這種數據類型包裝成可選類型:
1:在原有類型的后面添加 ? ,這種可選類型必須強制解析才能獲得被包裝的值。
2:在原有類型的后面添加 ! ,這種可選類型可有Swift隱式的解析被包裝的值。
其實你掌握了可選類型的使用,可選鏈就沒什么難度了,下面具體用法下面鏈接講的很清楚:
八:構造器
構造器用於完成實例的構造過程,這個過程包括為實例中的每個存儲屬性社會中初始值和執行必要的准備和初始化任務, 與OC的構造器不同,Swift的構造器無需顯式的聲明返回值的類型,也無需顯式使用 return返回實例, Swift 的構造器構造出來的實例由系統隱式的返回。它的本質其實就是一個或者多個名為 init 的函數。
九:可能失敗的構造器
有些時候,枚舉,結構體,類的構造可能不能成功的返回該類型的實例,比如你傳入的構造器參數數據無效等等,這時候就定義了"可能失敗的構造器"。
可能失敗的構造器使用 init? 或者 init!來進行定義,在這種構造我的執行體內返回使用 return nil 來表示構造失敗,該構造器返回了一個nil(缺失值)。
Swift 不允許定義兩個具有相同形式類別的構造器,即使一個是可能失敗的構造器,一個是普通的構造器。
后序的關於面向對象沒寫完的,還在制造中,有錯誤的地方歡迎指正,也可以加我QQ。。一起討論學習