代码之家  ›  专栏  ›  技术社区  ›  Coder-256

Swift协议作为类的通用参数

  •  2
  • Coder-256  · 技术社区  · 7 年前

    我正在尝试创建一个类( ProtocolPrinter )它将协议作为通用参数。为什么这个不能编译?

    import Foundation
    
    @objc protocol MyProtocol {
        func foo()
    }
    
    class MyConformingClass: MyProtocol {
        func foo() {
            print("Foo!")
        }
    }
    
    class ProtocolPrinter<T: Protocol> {
        func printT() {
            print("T: \(T.self)")
        }
    
        func dosomethingWithObject(_ object: T) {
            if let object = object as? MyProtocol {
                object.foo()
            } else {
                print("I don't know what object this is: \(object).")
            }
        }
    }
    
    let x = MyConformingClass()
    x.foo() // Foo!
    
    let myProtocolMeta: Protocol = MyProtocol.self // No error.
    
    ProtocolPrinter<MyProtocol>()                        // 'ProtocolPrinter' requires that 'MyProtocol' inherit from 'Protocol'
    ProtocolPrinter<MyProtocol.self>()                   // (treats "<" and ">" as operators)
    ProtocolPrinter<MyProtocol.Type>()                   // 'ProtocolPrinter' requires that 'MyProtocol.Type' inherit from 'Protocol'
    ProtocolPrinter<MyProtocol.Type.self>()              // (treats "<" and ">" as operators)
    ProtocolPrinter<MyProtocol.Protocol>()               // type 'MyProtocol.Protocol' does not confor
    ProtocolPrinter<MyProtocol.Protocol.self>()          // (treats "<" and ">" as operators)
    ProtocolPrinter<MyProtocol.Protocol.Type>()          // type 'MyProtocol.Protocol.Type' does not conform to protocol 'MyProtocol'
    ProtocolPrinter<MyProtocol.Protocol.Type.self>()     // (treats "<" and ">" as operators)
    ProtocolPrinter<MyProtocol.Protocol.Protocol>()      // cannot use 'Protocol' with non-protocol type 'MyProtocol.Protocol'
    ProtocolPrinter<MyProtocol.Protocol.Protocol.Type>() // cannot use 'Protocol' with non-protocol type 'MyProtocol.Protocol'
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Coder-256    7 年前

    事实证明,您只需要指定一个 @objc protocol 所有其他协议(也必须是 @objc协议 s) 符合,例如:

    import Foundation
    
    @objc protocol SuperProtocol {}
    @objc protocol MyProtocol: SuperProtocol {
        func foo()
    }
    
    class MyConformingClass: MyProtocol {
        func foo() {
            print("Foo!")
        }
    }
    
    class ProtocolPrinter<T: SuperProtocol> {
        func printT() {
            print("T: \(T.self)")
        }
    
        func dosomethingWithObject(_ object: T) {
            if let object = object as? MyProtocol {
                object.foo()
            } else {
                print("I don't know what object this is: \(object).")
            }
        }
    }
    
    let x = MyConformingClass()
    x.foo() // Foo!
    MyProtocol.Protocol.self
    let myProtocolMeta: Protocol = MyProtocol.self
    
    ProtocolPrinter<MyProtocol>().dosomethingWithObject(MyConformingClass()) // Foo!