一秃踩、面向?qū)ο?/h4>
傳統(tǒng)的面向?qū)ο箝_發(fā)思維方式是將類中實現(xiàn)的相似方法抽取出來,接著放入一個Base類业筏,然后繼承于Base類后各個類即可找擁有相同的方法憔杨,不用再一個個手動實現(xiàn)。
具體代碼請參考前面分析斗魚的文章蒜胖。傳送門
二消别、面向函數(shù)
Swift 支持 map, reduce, filter, flatmap 這類去除中間狀態(tài)、數(shù)學(xué)函數(shù)式的方法台谢,更加強(qiáng)調(diào)運(yùn)算結(jié)果而不是中間過程寻狂,所以我們也說Swift是面向函數(shù)編程。
三朋沮、面向協(xié)議(POP)
1蛇券、OC和Swift的面向協(xié)議的區(qū)別
OC無法做到面向協(xié)議開發(fā),而Swift可以,因為Swift可以做到協(xié)議方法的具體實現(xiàn)怀读,而OC不行诉位。面向協(xié)議開發(fā)的核心是:模塊化(組件化)。
注意:swift可以做到協(xié)議方法的具體實現(xiàn)菜枷。也就是說苍糠,聲明協(xié)議方法之后,擴(kuò)展extension該協(xié)議啤誊,然后實現(xiàn)該協(xié)議方法岳瞭。讓類遵守該代理,然后這個類就可以直接調(diào)用協(xié)議的方法了蚊锹。
注意兩點:
a.protocol中可以聲明變量瞳筏,方便在協(xié)議方法中使用。
b.協(xié)議方法的具體實現(xiàn)需要在extension中來實現(xiàn)牡昆。
示例如下:
- 聲明協(xié)議
protocol NetworkToolProtocol {
// MARK: - --------------------------------- 首頁 home ---------------------------------
// MARK: 首頁頂部新聞標(biāo)題的數(shù)據(jù)
static func loadHomeNewsTitleData(completionHandler: @escaping (_ newsTitles: [HomeNewsTitle]) -> ())
// MARK: 首頁頂部導(dǎo)航欄搜索推薦標(biāo)題內(nèi)容
static func loadHomeSearchSuggestInfo(_ completionHandler: @escaping (_ searchSuggest: String) -> ())
// MARK: 獲取首頁姚炕、視頻、小視頻的新聞列表數(shù)據(jù)
static func loadApiNewsFeeds(category: String, ttFrom: TTFrom, _ completionHandler: @escaping (_ maxBehotTime: TimeInterval, _ news: [NewsModel]) -> ())
}
- 實現(xiàn)協(xié)議
extension NetworkToolProtocol {
// MARK: - --------------------------------- 首頁 home ---------------------------------
/// 首頁頂部新聞標(biāo)題的數(shù)據(jù)
/// - parameter completionHandler: 返回標(biāo)題數(shù)據(jù)
/// - parameter newsTitles: 首頁標(biāo)題數(shù)組
static func loadHomeNewsTitleData(completionHandler: @escaping (_ newsTitles: [HomeNewsTitle]) -> ()) {
let url = BASE_URL + "/article/category/get_subscribed/v1/?"
let params = ["device_id": device_id,
"iid": iid]
Alamofire.request(url, parameters: params).responseJSON { (response) in
// 網(wǎng)絡(luò)錯誤的提示信息
guard response.result.isSuccess else { return }
if let value = response.result.value {
let json = JSON(value)
guard json["message"] == "success" else { return }
if let dataDict = json["data"].dictionary {
if let datas = dataDict["data"]?.arrayObject {
var titles = [HomeNewsTitle]()
titles.append(HomeNewsTitle.deserialize(from: "{\"category\": \"\", \"name\": \"推薦\"}")!)
titles += datas.flatMap({
HomeNewsTitle.deserialize(from: $0 as? NSDictionary)
})
completionHandler(titles)
}
}
}
}
}
}
........
- 繼承協(xié)議(結(jié)構(gòu)體或類都可以)
struct NetworkTool: NetworkToolProtocol {}
然后丢烘,通過NetworkTool直接就可以調(diào)用NetworkToolProtocol的方法了柱宦。
多多思考:
至此,我們就可以通過面向協(xié)議的方式給類定制不同的功能播瞳,也就是模塊化掸刊。可以發(fā)現(xiàn)Swift的面向協(xié)議編程跟c++的多繼承很相似赢乓。思考二:此時的NetworkToolProtocol是可以被任意類繼承的忧侧,如果需要特定繼承呢?我們該怎么處理牌芋?
約束:為了特定的繼承蚓炬,我們添加約束,比如只允許UserDiggViewController
類繼承姜贡。
extension NetworkToolProtocol where Self : UserDiggViewController{}
2试吁、為什么要使用POP編程?
Swift已經(jīng)是一門面向?qū)ο蟮恼Z言楼咳,類已經(jīng)滿足我們的所有需求熄捍,功能也很強(qiáng)大,為什么還要使用POP呢母怜?
我們知道余耽,在Swift中,值類型優(yōu)先于類苹熏。然而碟贾,面向?qū)ο蟛荒芎芎玫嘏c結(jié)構(gòu)體和枚舉一起工作:因為結(jié)構(gòu)體和枚舉不能被繼承币喧。
因此,作為面向?qū)ο蟮囊淮筇卣?------繼承
袱耽,就不能應(yīng)用于值類型了杀餐。
3、面向協(xié)議編程(POP)的好處有什么呢朱巨?
- 結(jié)構(gòu)體史翘、枚舉等值類型也可以使用。
- 可以繼承多個協(xié)議冀续,彌補(bǔ)Swift中類單繼承的不足琼讽。
- 增強(qiáng)代碼的可擴(kuò)展性,減少代碼的冗余洪唐。
- 讓項目更加組件化钻蹬,代碼可讀性更高。
- 讓功能代碼組成一個功能塊凭需,更便于單元測試问欠。
使用示例:
假設(shè)我們有一個ViewController,它繼承自UIViewController功炮,我們向其新添加一個方法 customMethod:
classViewController:UIViewController {
func customMethod{
}
}
此時溅潜,我們有另外個繼承自UITableViewController的OtherViewController,同樣也需要向其添加方法customMethod:
classViewController:UITableViewController {
func customMethod{
}
}
此時,問題就出現(xiàn)了薪伏,很難在不同繼承關(guān)系的類里共用代碼。此時的解決辦法就有一下幾種:
- 復(fù)制粘貼方法粗仓,這種方法是最糟糕的解決方案嫁怀。
- 創(chuàng)建一個基類添加上共享的代碼,或者在UIViewController上添加 extension借浊√潦纾可是隨著方法的增多,會讓基類由于職責(zé)不明蚂斤,什么方法都扔進(jìn)基類存捺,完全區(qū)分不了哪個類走了基類,很快變成了垃圾堆曙蒸。這樣會對項目造成混亂的影響捌治。
- 依賴注入,通過外界傳入一個帶有 customMethod的對象纽窟,用新的類型來提供這個功能肖油。這是一個稍好的方式,但是引入額外的依賴關(guān)系臂港,也是我們不愿意看到森枪。
使用POP解決問題
a.定義一個含有customMethod的協(xié)議ex;
protocol ex {
func customMethod;
}
b.在extension中為customMethod添加實現(xiàn):
extension ex {
func customMethod{
//方法實現(xiàn)
}
}
有了這個協(xié)議擴(kuò)展视搏,只要在ViewController和OtherViewController遵循ex協(xié)議,就可以直接使用customMethod方法了县袱。
4浑娜、協(xié)議繼承
協(xié)議可以從其它協(xié)議繼承,然后在它繼承的需求之上添加功能式散,因此可以提供更細(xì)粒度和更加靈活的設(shè)計筋遭。
5、協(xié)議的組合
類杂数、結(jié)構(gòu)體和枚舉可以符合多個協(xié)議宛畦,他們可以采用多個協(xié)議的默認(rèn)實現(xiàn)。是不是和多繼承很類似揍移?這種組合方式不僅比將所有需要的功能壓縮到一個基類中更靈活次和,而且也適用于值類型。
class FirstVC:ex1,ex2{
}
ex1,ex2,代表兩個不同的協(xié)議