5月27日 11:50

Swift 泛型怎么用?泛型约束和关联类型有什么区别?

泛型让你写"适用于多种类型"的代码,编译器在使用时确定具体类型。函数用 <T> 声明占位类型,类型用 <Element> 声明泛型参数。泛型保证了类型安全——编译期检查,不会运行时类型错误。

泛型约束限制 T 必须满足什么条件:<T: Equatable> 要求 T 可比较,<T: AnyObject> 要求 T 是类类型。where 子句做更复杂的约束:where T.Element: Comparable

关联类型是协议里的泛型——用 associatedtype Item 声明,遵循协议的类型确定具体类型。有关联类型的协议不能直接当类型用,需要 some Protocolany Protocol

追问

泛型约束和 where 子句有什么区别?

泛型约束写在 <T: Protocol> 里,是简单的"遵循某个协议"。where 子句写在函数签名后面,可以做更精确的约束:where T.Element == U.Element(两个泛型的元素类型相同)、where T: Collection, T.Index == Int。简单约束用 : 语法,复杂约束用 where。

some 和 any 有什么区别?

some Protocol 是不透明类型——编译器知道具体类型但调用方不知道,性能好(无动态派发)。any Protocol 是存在类型——运行时可以是任何遵循协议的类型,有装箱开销。函数返回值优先用 some(Swift 5.7+),需要存储不同类型时用 any。

泛型函数和函数重载有什么区别?

重载为每种类型写一个函数,泛型只写一个。重载可以在每个版本做不同实现,泛型所有类型共享同一个实现。如果不同类型需要不同逻辑,用重载或协议扩展。如果逻辑相同只是类型不同,用泛型。

泛型的类型擦除是什么?

有关联类型的协议不能直接当类型用——let items: Container 编译不过,因为 Container 的 Item 类型不确定。类型擦除用包装器隐藏具体类型:AnyContainer 包装任何 Container,对外只暴露 Item 类型。标准库的 AnySequence、AnyPublisher 都是类型擦除。

写段代码

swift
// 泛型函数 func first<T>(of array: [T]) -> T? { array.first } // 泛型约束 func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? { array.firstIndex(of: value) } // where 子句 func allEqual<C: Collection>(in collection: C) -> Bool where C.Element: Equatable { guard let first = collection.first else { return true } return collection.allSatisfy { $0 == first } } // 关联类型 protocol Container { associatedtype Item var count: Int { get } mutating func append(_ item: Item) } struct Stack<Element>: Container { private var items: [Element] = [] var count: Int { items.count } mutating func append(_ item: Element) { items.append(item) } mutating func pop() -> Element? { items.popLast() } }
标签:Swift