Swiftswift

Swift基础语法(十二)扩展

2022-05-16  本文已影响0人  iOS之文一

Swift基础学习文章汇总

扩展的核心在于扩展的内容不能改变原有实例的内存结构、不能修改原有功能,本文对常见的计算属性、下标、协议、初始化器、声明、协议实现、泛型的扩展进行了示例分析

主要内容:

  1. 扩展认识
  2. 扩展示例

扩展

扩展可以为枚举、结构体、类、协议增加新功能,并且不能更改原有功能以及实例内存,有点类似于OC中的分类

扩展不可以进行的操作:

  1. 不能覆盖原有功能方法
  2. 不能增加存储属性
  3. 不能向已有的属性添加属性观察器
  4. 不能添加父类
  5. 不能添加指定初始化器,不能添加反初始化器

增加计算属性

代码:

//1、增加计算属性
extension Double {
    var km: Double { self * 1_000.0 }
    var m: Double { self }
    var dm: Double { self / 10.0 }
    var cm: Double { self / 100.0 }
    var mm: Double { self / 1_000.0 }
}
var d = 10.0
print(d.km)
print(d.m)
print(d.dm)
print(d.cm)
print(d.mm)

增加下标

代码:

//2、增加下标
extension Array {
    subscript(nullable idx: Int) -> Element? {
        if (startIndex..<endIndex).contains(idx) {
            return self [idx]
        }
        return nil
    }
}
var arr: Array<Int> = [20,10,30]
print(arr[nullable: 3] as Any)

说明:
1、原有类的泛型在扩展中依然可以使用
2、这里的扩展是用给数组增加越界判断
3、注意这里的范围是..<,也就是不包含最后一个值,这是因为endIndex并不是指向最后一个值的索引,而是最后一个值的下一位索引
4、比如这里的endIndex其实是3,而不是2
5、如果数组为空,那么就是0..<0,此时在语义上解释既包括0也不包括0,其实是不包括0
6、因为返回的是可选项,所以使用as Any

增加协议

代码:

//3、增加协议
class Person {
    var age: Int
    var name: String
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
}
extension Person : Equatable {
    //扩展一个方法
    static func == (left: Person, right: Person) -> Bool {
        left.age == right.age && left.name == right.name
    }
    //只能扩展便捷初始化器
    convenience init() {
        self.init(age: 0, name: "")
    }
}

let p1 = Person.init(age: 10, name: "WY")
let p2 = Person.init(age: 20, name: "WY")
print(p1 == p2)//false

说明:

  1. 可以给类型扩展一个协议
  2. 另外类中扩展init只能扩展便捷初始化器

增加初始化器

代码:

//4、增加初始化器
struct Point {
    var x: Int = 0
    var y: Int = 0
}
extension Point {
    init(_ point: Point) {
        self.init(x: point.x, y: point.y)
    }
}
//扩展初始化器后,并不会覆盖之前的初始化器,没有覆盖,而只是扩展
var p41 = Point()
var p42 = Point(x: 10)
var p43 = Point(y: 20)
var p44 = Point(x: 10, y: 20)
var p45 = Point(p44)

说明:
1、给结构体扩展了一个初始化器,结构体可以直接扩展一个初始化器,因为它是不区分便捷的还是指定初始化器
2、注意此时不会覆盖以前的四个初始化器,这也容易理解,在Swift中扩展是不能更改原有类型中的功能和内存结构的

必需初始化器不能添加扩展中

必需初始化器不能添加到扩展中.png

说明:
1、我们知道一个类遵守协议时,并且实现这个协议的init方法,需要使用required,因为需要子类也实现这个init
2、但是这个初始化器只能加载类中,而不能加在类的扩展中,也容易理解,这个扩展是新增功能,但是required init()是必需存在的,必需存在的东西自然要放在类本身中
3、因此这个与是否遵守协议无关,只要是required,那么就必须放在类本身中

增加已遵守协议实现的协议声明

如果一个类型已经实现了协议的所有要求,但是没有声明遵守这个协议,那么可以通过扩展来让他遵守
代码:

//5、增加协议声明
protocol TestProtocol {
    func test()
}
class TestClass {
    func test() {
        print("test")
    }
}
extension TestClass : TestProtocol {}
TestClass().test()

判断奇数的案例

/*
 判断奇数案例
两种方案:
 1. 创建isOdd函数,传入遵守BinaryInteger协议的类型,进行比较
 2. 扩展BinaryInteger协议,增加isOdd方法
 */
func isOdd<T: BinaryInteger>(_ i: T) -> Bool {
    i % 2 != 0
}
extension BinaryInteger {
    func isOdd() -> Bool { self % 2 != 0 }
}
print(10.isOdd())//false
print((-3).isOdd())//true

说明:
1、此处给协议可扩展了一个功能,用来判断奇数
2、在使用泛型时,又需要指明遵守某个协议,防止其他乱七八糟的类型也进来判断
3、BinaryInteger协议是所有整数类型遵守的协议,因此这里放上它

增加协议实现

代码:

//6、增加协议实现
protocol TestProtocol6 {
    func test1()
}
//增加协议方法实现,增加协议方法
extension TestProtocol6 {
    func test1() {
        print("TestProtocol test1")
    }
    func test2() {
        print("TestProtocol test2")
    }
}
//类中自己再实现一下方法
class TestClass6 : TestProtocol6 {
func test1() { print("TestClass test1") }
func test2() { print("TestClass test2") }
}
var cls = TestClass6()
cls.test1() // TestClass test1
cls.test2() // TestClass test2  隐式遵守协议,会打印类的实现
var cls2: TestProtocol6 = TestClass6()
cls2.test1() // TestClass test1
cls2.test2() // TestProtocol test2 显式遵守协议,会打印默认的实现

说明:
1、扩展协议可以给协议中定义的方法供实现,这就是默认实现
2、遵守该协议的类如果不去实现也不会报错,因为已经有了默认实现
3、扩展协议还可以增加功能
4、注意此时的打印,如果cls显式或隐式的显示遵守了TestProtocol协议,会有不同的打印结果

增加泛型

代码:

//7、增加泛型
//下是一个模拟栈的类
class Stack<E> {
    var elements = [E]()
    func push(_ element: E) {
        elements.append(element)
    }
    func pop() -> E { elements.removeLast() }
    func size() -> Int { elements.count }
}
// 1、扩展中依然可以使用原类型中的泛型类型
extension Stack {
    func top() -> E { elements.last! }
}
// 2、符合条件才扩展(给Stack增加泛型,并添加泛型约束
extension Stack : Equatable where E : Equatable {
    static func == (left: Stack, right: Stack) -> Bool {
        left.elements == right.elements
    }
}

说明:
1、扩展可以使用原类型的泛型
2、扩展可以增加泛型

上一篇下一篇

猜你喜欢

热点阅读