协议
// 协议
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)")
}