简体   繁体   English

在 swift 的泛型中使用带有类型约束的协议

[英]Use protocol in swift's generic with type constraint

I write a custom storage, that should supports only objects that conform some protocol:我编写了一个自定义存储,它应该只支持符合某些协议的对象:

protocol MyBaseProtocol {
    func baseMethod()
}
class Stor <ElementType : MyBaseProtocol>  {
    var storage = [ElementType]()
    
    func addElement(_ element: ElementType) {
        storage.append(element)
    }
}

Next I've created a child protocol and want to store only objects what conform the child protocol:接下来我创建了一个子协议,并且只想存储符合子协议的对象:

protocol MyProtocol : MyBaseProtocol {
    func method()
}
var otherStorage = Stor<MyProtocol>() //compilation error
class C1 : MyProtocol {
    func method() {
    }
    func baseMethod() {
    }
}
class S1 : MyProtocol {
    func method() {
    }
    func baseMethod() {
    }
}
otherStorage.addElement(C1())
otherStorage.addElement(S1())

I've got an error:我有一个错误:

Value of protocol type 'MyProtocol' cannot conform to 'MyBaseProtocol'; only struct/enum/class types can conform to protocols

How I can create an instance of Stor that can store only objects that conform MyBaseProtocol?如何创建一个只能存储符合 MyBaseProtocol 的对象的 Stor 实例?

You are running into the issue of protocols not conforming to themselves .您遇到了协议不符合自身的问题。 You can resolve this by creating a concrete type conforming to MyProtocol and converting all your conforming types to that before storing them in your Store .您可以通过创建一个符合MyProtocol的具体类型并将所有符合的类型转换为该类型,然后再将它们存储在您的Store中来解决此问题。

class AnyMyProtocol: MyProtocol {
    private let _baseMethod: () -> ()
    private let _method: () -> ()

    init(base: MyProtocol) {
        _baseMethod = base.baseMethod
        _method = base.method
    }

    func baseMethod() {
        _baseMethod()
    }

    func method() {
        _method()
    }
}

extension MyProtocol {
    var erased: AnyMyProtocol {
        AnyMyProtocol(base: self)
    }
}

var otherStorage = Store<AnyMyProtocol>()

class C1 : MyProtocol {
    func method() {}
    func baseMethod() {}
}

struct S1 : MyProtocol {
    func method() {}
    func baseMethod() {}
}

enum MyEnum: MyProtocol {
    case some

    func method() {}
    func baseMethod() {}
}

otherStorage.addElement(C1().erased)
otherStorage.addElement(S1().erased)
otherStorage.addElement(MyEnum.some.erased)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM