Swift学习笔记-泛型

泛型能让我们使用的类型和函数使用未知的类型,许多内置类型,例如可空类型,数组和字典都是用泛型实现的。

泛型类型

下面的结构体实现了一个简单的栈,可以对Int类型执行push和pop操作。

struct Stack{
    var items = [Int]()
    
    mutating func push(newitem:Int){
        items.append(newitem)
    }
    
    mutating func pop() ->Int?{
        guard !items.isEmpty else{
            return nil
        }
        return items.removeLast()
    }
    
}

var stack=Stack()
stack.push(newitem:1)
stack.push(newitem:2)
print(stack.pop())
print(stack.pop())

但是如果我们需要对其他类型进行入栈和出栈操作,那就得再编写一个栈类型,使用泛型可以让这个栈支持任意类型。改写后的代码如下,Swift的泛型语法和Java差不多。

struct Stack<T>{
    var items = [T]()
    
    mutating func push(newitem:T){
        items.append(newitem)
    }
    
    mutating func pop() ->T?{
        guard !items.isEmpty else{
            return nil
        }
        return items.removeLast()
    }
    
}

var stack=Stack<Int>()
stack.push(newitem:1)
stack.push(newitem:2)
print(stack.pop())
print(stack.pop())

多个占位类型

泛型可支持多个占位类型,代码如下。

struct Stack<T,U,X>{
    var items = [T]()
    var items1 = [U]()
    var items2 = [X]()
    ...
}
var stack=Stack<Int,String,Double>()

泛型函数和方法

泛型函数需要在函数参数列表前声明占位类型,然后可以在参数和返回值中使用这些占位类型。

func getSelf<T>(arg:T)->T{
    return arg
}

print(getSelf(arg: "hello world!"))

类型约束

有时候我们需要对传入的类型做一些限制,可以通过类型约束实现,有两种约束:一种是类型必须是给定类的子类,还有一种是类型必须符合一个协议。

func checkEqual<T:Equatable>(first:T,second:T)->Bool{
    return first==second
}
print(checkEqual(first: 1, second: 1))
print(checkEqual(first: "123", second: "456"))

当占位类型比较复杂时,我们还可以使用where语句进一步约束占位类型,如下代码要求newitems的元素必须是T类型。

struct Stack<T>{
    var items = [T]()
    
    mutating func push(newitem:T){
        items.append(newitem)
    }
    
    mutating func pushAll<S:Sequence>(newitems:S)
        where S.Iterator.Element==T {
            for item in newitems {
                self.push(newitem: item)
                print("push \(item)")
            }
    }
    
    mutating func pop() ->T?{
        guard !items.isEmpty else{
            return nil
        }
        return items.removeLast()
    }
}


var stack=Stack<Int>()
stack.pushAll(newitems:[1,2,3,4,5,6])

关联类型协议

协议不支持泛型,但是支持另外一种特性:关联类型,在协议内部可以使用associatedtype关键字声明一个占位类型,符合这个协议的类型应该在其内部为占位类型提供typealias定义。

protocol InteratorProtocol {
    associatedtype Element
    mutating func next() -> Element?
}


struct Stack<T>:InteratorProtocol {
    typealias Element = Int
    
    mutating func next() -> Element? {
        return 0
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容