携手创造,一起成长!这是我参与「日新计划 8 月更文挑战」的第26天,点击查看活动概况

Swift基础语法文章汇总

本文主要知道面向协议编程和面向目标编程的优缺点,以及如何完成面向协议编程。

主要内容:

  1. 面向协议的知道
  2. 面向协议的运用

1、 知道

面向协议编程( Protocol Oriented Programming ,简称POP),Swift中既能够面向目标,也能够面向协议,在Swift开发中两者是相得益彰的。
在Swift的规范库中,能见到很多POP的影子,由于Swift协议有扩展功用,能够支持更强大的功用。
因此在Swift中很多运用结构体、运用协议,而不是类

2、 扩展功用

2.1 OOP的缺乏

代码:

/*
 1、OOP的缺乏
 */
func test21() {
    class BVC: UIViewController {
        func run() {
            print("run")
        }
    }
    class DVC: UITableViewController {
        func run() {
            print("run")
        }
    }
}
/*
 POP的处理方案,经过恪守协议来完成
 */
protocol Runnable {
    func run()
}
extension Runnable {
    func run() {
        print("run")
    }
}
func test22() {
    class BVC: UIViewController, Runnable {}
    class DVC: UITableViewController, Runnable {}
}

阐明:

  1. 这里如何将两个办法抽取出来,基于OOP有这么几种处理方案
  2. 将run办法放到另一个目标A中,然后BVC、DVC拥有目标A特点。可是这样会多增加额定的依赖关系
  3. 将run办法统一增加到UIViewController分类中。可是UIViewController会越来越臃肿,而且会影响它的其他一切子类
  4. 采用多承继将run办法抽取到新的父类,可是会增加程序设计复杂度,产生菱形承继等问题,需要开发者额定处理
  5. 因此这种情况下运用POP,增加一个声明run办法的协议,BVC和DVC都恪守该协议就能够处理。

2.2 运用协议给字符串扩展一个功用

经过给字符串扩展一个功用为案例进行阐明协议在实际开发中的效果,最终经过协议能够给恣意的类型扩展恣意的功用,有很好的封装性和扩展性

代码:

//结构体基类
struct WY<Base> {
    let base: Base
    init(_ base: Base) {
        self.base = base
    }
}
//协议
protocol WYCompatible {}
//给协议扩展两个特点,一个是类一个是目标
extension WYCompatible {
    static var WY: WY<Self>.Type {
        get { WY<Self>.self }
        set {}
    }
    var WY: WY<Self> {
        get { WY(self) }
        set {}
    }
}
extension String: WYCompatible {}
extension NSString: WYCompatible {}
//给WY结构体扩展一个办法numberCount
extension WY where Base: ExpressibleByStringLiteral {
    func numberCount() -> Int {
        let string = base as ! String
        var count = 0
        for c in string where ("0"..."9").contains(c) {
            count += 1
        }
        return count
    }
}
func test21() {
    var s1: String = "123fdsf434"
    var s2: NSString = "123fdsf434"
    var s3: NSMutableString = "123fdsf434"
    print(s1.WY.numberCount())
    print(s2.WY.numberCount())
    print(s3.WY.numberCount())
}

阐明:

  1. 给字符串设置协议,给协议增加扩展,扩展里增加两个变量WY
  2. 而在WY结构体中扩展办法。
  3. 为了扩展的类型愈加通用,结构体中运用泛型
  4. 为了给不同的泛型增加不同的办法,给结构体运用扩展增加办法
  5. 给结构体增加类型办法,这里留意类型变量的设置。
  6. 此处给NSString也恪守MJCompatible协议,这样它也就能够拥有了这个功用

留意:
1、为了能够给恣意类型增加额定功用,能够将该功用抽取到一个结构体中去执行
2、为了给类型增加恣意功用,能够将功用放到结构体的扩展中,而且恪守某个协议

3、 判别类型

以判别Array类型为例来阐明

代码:

//目标的类型判别
func isArray(_ value: Any) -> Bool {
    value is [Any]
}
print(isArray( [1, 2] ))
print(isArray( ["1", 2] ))
print(isArray( NSArray() ))
print(isArray( NSMutableArray() ))
//类的类型判别,需要增加协议,只需都恪守ArrayType协议就认为是数组
protocol ArrayType {}
extension Array: ArrayType {}
extension NSArray: ArrayType {}
func isArrayType(_ type: Any.Type) -> Bool {
    type is ArrayType.Type
}
print(isArrayType([Int].self))
print(isArrayType([Any].self))
print(isArrayType(NSArray.self))
print(isArrayType(NSMutableArray.self))

阐明:

  • 目标判别很简单,只需要判别类型即可
    • [Any]表明任何类型的数组,因此它就能够表明恣意的数组
    • 留意这里能够判别NSArray和NSMutableArray
  • 关于类型判别无法经过元类型来判别,只能经过协议判别
    • 由于[Any].type与[Int].type表明为两个不同的类型,无法进行判别
    • 因此关于类型的判别,能够经过判别数组所恪守的协议
    • 一切的数组均会恪守ArrayType协议,所以能够经过它来判别

4、总结

  • 优先考虑创建协议,而不是父类(基类)
  • 优先考虑值类型( struct、 enum ),而不是引证类型( class)
  • 面向协议编程,优先考虑运用协议,而不是父类
  • 需要巧用协议扩展
  • 不要为了面向协议而运用协议