Swift基础

swift泛型约束

2021-09-20  本文已影响0人  gerrywanggang

泛型在实际应用中往往要给泛型添加约束。
简单举一个例子:

class Human<T, U>: Codable where T: Codable, U: Codable {
    var name: T
    var age: U
    
    init(name: T, age: U) {
        self.name = name
        self.age = age
    }
}

在上面的代码中where T: Codable, U: Codable就是给泛型添加约束。加上约束之后,在创建Human的实例的时候name和age必须满足Codable协议

泛型约束的添加时机,可以在类/结构/协议定义的时候的添加,也可以在其extension中添加。在extension中添加将更加灵活。
在class扩展中添加泛型约束

class SwitchSkin<BASE> {
    var base: BASE
    init(_ base: BASE) {
        self.base = base
    }
}

extension SwitchSkin where BASE : UIView {
    func setSkinBackground(color: UIColor) {
        base.backgroundColor = color
    }
}

在协议扩展中添加泛型约束

protocol SwitchSkinCompatiale {
    associatedtype OBJ
    var ss: SwitchSkin<OBJ> { get }
}

extension SwitchSkinCompatiale where OBJ: NSObject {
    func sayHello() {
        print("Hello World!")
    }
}

在协议中使用泛型时,扩展中直接使用Self, 这个方式非常灵活。相当于直接自动指定为泛型为自身的类型。

final class SwitchSkin<BASE> {
    var base: BASE
    init(_ base: BASE) {
        self.base = base
    }
}

extension SwitchSkin where BASE : UITextField {
    func setSkinBackground(color: UIColor) {
        base.backgroundColor = color
    }
    
    func setText(text: String) {
        base.text = text
        print(base.text ?? "")
    }
}

protocol SwitchSkinCompatible {
    associatedtype T
    var ss: SwitchSkin<T> { get }
}

extension SwitchSkinCompatible {
    var ss: SwitchSkin<Self> {
        return SwitchSkin.init(self)
    }
}

extension NSObject: SwitchSkinCompatible {}

UITextField.init().ss.setText(text: "123")

输出为
123

不同的泛型可以通过约束条件建立关联,如函数和类中的泛型。如下

class Human<T, U>: Codable where T: Codable, U: Codable {
    var name: T
    var age: U

    init(name: T, age: U) {
        self.name = name
        self.age = age
    }

    func sameNameTypeSuperman<S: SupermanType>(superman: S) -> S where S.NAMETYPE == T {
        return Superman.init(name: name) as! S
    }
}

protocol SupermanType {
    associatedtype NAMETYPE
}

struct Superman<NAMETYPE>: SupermanType {
    var name: NAMETYPE
}

let human = Human.init(name: "xiaoli", age: 18)
let s = human.sameNameTypeSuperman(superman: Superman.init(name: "super xiao li"))
print(s)

上面的例子中,sameNameTypeSuperman函数中,SupermanType协议中的NAMETYPE和Human类中的name的泛型T建立了约束。

总结, 泛型约束用在了下列一些地方:

  1. 泛型定义的地方,直接加上约束;
  2. extension的时候,通过泛型约束建立条件扩展;
  3. 不同的泛型定义之间建立约束条件,如函数中的泛型和类中的泛型。
上一篇 下一篇

猜你喜欢

热点阅读