- 泛型视图解决存储不同的数据类型,或者方法的入参是不同的数据类型。这样可以优雅的减少了很多不必要的重复代码。
func exchangeTwoValue<T>(a:inout T, b: inout T){
let temp = a
a = b
b = temp
}
var a = 3
var b = 4
exchangeTwoValue(a: &a, b: &b)
print(String(a) + " " + String(b))
var c = "abc"
var d = "123"
exchangeTwoValue(a: &c, b: &d)
print(String(c) + " " + String(d))
//系统库函数解决交互两个值
swap(&c, &d)
print(String(c) + " " + String(d))
复制代码
- 利用泛型实现一个自定义栈
//1. 利用泛型实现自定义栈
struct Stack<Element> {
var items = [Element]()
mutating func push(_ a: Element){
items.append(a)
}
mutating func pop(){
items.removeLast()
}
}
var aStack = Stack<Any>()
aStack.push(1)
aStack.push(2.0)
aStack.push("1")
print(aStack.items)
aStack.pop()
print(aStack.items)
复制代码
- 对泛型类型扩展
//2. 利用扩展返回栈顶
extension Stack {
var topStack: Element? {
return items.isEmpty ? nil : items.last
}
}
print(aStack.topStack as Any)
复制代码
- 类型约束
func findIndex<T: Equatable>(findValue: T, array: [T]) -> Int?{
for (index, value) in array.enumerated(){
if value == findValue {
return index
}
}
return nil
}
var a = [1,2,3,4,5]
print(findIndex(findValue: 3, array: a) as Any)
复制代码
- 关联类型
protocol Container {
associatedtype Item
mutating func append(item: Item)
var count: Int{get}
subscript(index: Int) -> Item { get }
}
struct Stack<Element>: Container {
var items = [Element]()
mutating func push(_ a: Element){
items.append(a)
}
mutating func pop(){
items.removeLast()
}
mutating func append(item: Element) {
push(item)
}
var count: Int{
return items.count
}
subscript(index: Int) -> Element {
return items[index]
}
}
var aStack = Stack<Any>()
aStack.push(1)
aStack.push(2.0)
aStack.push("1")
print(aStack.items)
print(aStack[2])
复制代码
- 协议里的关联类型可以添加条件
protocol Container {
associatedtype Item: Equatable
mutating func append(item: Item)
var count: Int{get}
subscript(index: Int) -> Item { get }
}
复制代码
- 泛型Where语句
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int {get}
subscript(item: Int) -> Item{get}
}
struct Stack<Element>: Container {
var items = [Element]()
mutating func append(_ item: Element) {
items.append(item)
}
var count: Int {
return items.count
}
subscript(item: Int) -> Item {
return items[item]
}
}
extension Array: Container {}
func allItemsMatch<T: Container, U: Container> (a: T, b: U) -> Bool
where T.Item == U.Item, T.Item: Equatable {
if a.count != b.count {
return false
}
for index in 0..<a.count {
if a[index] != b[index] {
return false
}
}
return true
}
var a = Stack<String>()
a.append("a")
a.append("b")
a.append("c")
a.append("d")
a.append("e")
a.append("f")
var b = [
"a",
"1",
"c",
"d",
"e",
"f"
]
print(allItemsMatch(a: a, b: b))
复制代码
- 扩展泛型协议使用where语句
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int {get}
subscript(item: Int) -> Item{get}
}
struct Stack<Element>: Container {
var items = [Element]()
mutating func append(_ item: Element) {
items.append(item)
}
var count: Int {
return items.count
}
subscript(item: Int) -> Item {
return items[item]
}
}
extension Array: Container {}
func allItemsMatch<T: Container, U: Container> (a: T, b: U) -> Bool
where T.Item == U.Item, T.Item: Equatable {
if a.count != b.count {
return false
}
for index in 0..<a.count {
if a[index] != b[index] {
return false
}
}
return true
}
extension Stack where Element: Equatable {
//1. 扩展判断是否是栈顶
func isTopStack(item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
//2. 扩展判断栈低
func isBottomStack(item: Element) -> Bool {
return count >= 1 && items[0] == item
}
}
var aStack = Stack<String>()
aStack.append("a")
aStack.append("b")
aStack.append("c")
print(aStack.isTopStack(item: "c"))
print(aStack.isBottomStack(item: "b"))
//扩展Container协议,新增如果每个元素都是小数类型,那么可以计算平均值
extension Container where Item == Double {
func avg() -> Double {
var sum = 0.0
for item in 0..<count{
sum += self[item]
}
return sum/Double(count)
}
}
var b = [
1.0,
2.0,
3.0,
4.0
]
print(b.avg())
复制代码
- 泛型下标
// 1. 封装数据结构
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int{get}
subscript(index: Int) -> Item{get}
}
extension Array: Container {}
struct Stack<Element>: Container {
var items = [Element]()
mutating func append(_ item: Element) {
items.append(item)
}
var count: Int {
return items.count
}
subscript(index: Int) -> Element {
return items[index]
}
}
// 2. 给两种数据结构扩展一个方法
extension Container {
subscript<T: Sequence>(set: T) -> [Item]
where T.Iterator.Element == Int {
var items = [Item]()
for item in set{
items.append(self[item])
}
return items
}
}
var aStack = Stack<String>()
aStack.append("a")
aStack.append("b")
aStack.append("c")
aStack.append("d")
print(aStack[[0,2,3]])
//打印如下
//["a", "c", "d"]
复制代码
- 总结
- 泛型视图解决存储多种数据类型,和方法的入参是多种数据类型。
- 一个方法入参不用泛型切其实可以用Any来解决。
- 利用Any来代替泛型不好,我们应该在方法入参用泛型。
- 泛型可以做到入参和返回值得统一性。但是Any做不多。
- 泛型可以在调用时候指定特定的数据类型。但是Any也做不到。 泛型