swift (四) 协议 扩展 泛型

16 阅读2分钟

协议

// 协议

protocol P_Animal{
    var age:Int { get set }
    var age1:Int {get}

    func eat()

    mutating func changAge()

    subscript(index:Int) -> String {get}
}

struct Animal:P_Animal{
    var age:Int = 0
    var age1:Int = 0

    func eat() {
        print("animal eat")
    }
    mutating func changAge() {
        age += 1
    }
    subscript(index: Int) -> String {
        "age is \(age)"
    }
}

class Cat:P_Animal{
    var age:Int = 0
    var age1:Int = 0

    func eat() {
        print("animal eat")
    }
    // 类不写mutating
    func changAge() {
        age += 1
    }
    subscript(index: Int) -> String {
        "age is \(age)"
    }
}

// 协议可以作为类型
let a:[P_Animal] = [Cat(), Cat()]

// 协议可以被继承
protocol P_Dog: P_Animal{
    func wanwan()
}

// 如果协议继承AnyObject,则只能类实现这个协议。枚举和结构体不行
protocol P_Class: AnyObject{

}


// 如果有继承和协议,继承放在第一个位置,协议放后面
//class Miao: Animal, P_Dog,P_Animal{
//
//}

// 协议也可以组合
//func sayHello(to:  P_Dog & P_Animal){
//
//}

扩展

扩展可以给已有类、结构体、枚举、协议追加新功能,不修改原有源码,不能新增存储属性。

// 给字符串扩展
extension String {
    func printAddress() {
        self.withCString { ptr in
            print("字符串内容地址: \(ptr)")
        }
    }
}

var s = "Hello world"
s.printAddress()

拓展增加计算属性和方法

// Swift 扩展不允许新增存储属性,仅支持计算属性
import Foundation

extension Int {
    // 计算属性可以不加mutating
    var doubleValue: Double {
        get {
            return Double(self * self)
        }
        set {
            self = Int(sqrt(newValue))
        }
    }
    // 非计算属性,普通方法修改当前值,需要加mutating
    mutating func add(by: Int){
        self += by
    }
}

var a: Int = 100
print(a.doubleValue)
a.doubleValue = 4
print(a.doubleValue)

a.add(by: 100)
print(a)

泛型

泛型函数

// T 为类型占位符,名称自定义(T、U、Element 都常用)
func swapValue<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = a
}

var num1 = 10, num2 = 20
swapValue(&num1, &num2)
print(num1, num2) // 20 10

var str1 = "A", str2 = "B"
swapValue(&str1, &str2)
print(str1, str2) // B A

泛型类型(类 / 结构体 / 枚举)

// 泛型结构体
struct Stack<T> {
    private var elements: [T] = []

    mutating func push(_ item: T) {
        elements.append(item)
    }
    mutating func pop() -> T? {
        elements.popLast()
    }
}

// 实例化,指定具体类型
var intStack = Stack<Int>()
intStack.push(1)
print(intStack.pop()!) // 1

var strStack = Stack<String>()
strStack.push("Swift")

多个占位符用逗号分隔:<T, U>

func pair<T, U>(first: T, second: U) -> (T, U) {
    return (first, second)
}

let res = pair(first: 100, second: "泛型")
print(res) // (100, "泛型")

类型约束

// T 必须遵守 Equatable(可比较协议)
func isEqual<T: Equatable>(_ a: T, _ b: T) -> Bool {
    return a == b
}

print(isEqual(5, 5))    // true
print(isEqual("Hi", "He")) // false





// 限定泛型只能是该类及其子类
class Animal {}
class Dog: Animal {}

// T 必须是 Animal 子类
func feed<T: Animal>(_ animal: T) {}

feed(Dog())



// 同时遵守多个协议,使用 `where` 子句(可读性更强)
protocol Named {
    var name: String { get }
}
protocol Age {
    var age: Int { get }
}

// 写法1:简写约束
func info1<T: Named & Age>(_ item: T) {
    print("\(item.name), \(item.age)")
}

// 写法2:where 分句(复杂场景推荐)
func info2<T>(_ item: T) where T: Named, T: Age {
    print("\(item.name), \(item.age)")
}