Swift协议作为类的通用参数

3

我正在尝试创建一个类(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. Protocol 类型是什么?!
  2. ProtocolPrinter 可以与符合 Protocol 的某些内容一起工作。通过拥有 class ProtocolPrinter<T: Protocol>,您已经将其作为要求。然而,MyProtocol 从未符合 Protocol
- mfaani
MyProtocol.self 符合 Protocol,它是一个类。这对于所有的 @objc 协议都是正确的。我还更新了我的答案,加入了更多的测试用例。 - Coder-256
1个回答

1

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

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!

1
把对象向下转型为特定协议会使协议的概念变得完全无用。这样,您也可以直接将其转换为MyConformingClass类,而不会失去任何功能或类型安全性。 - Andre
1
@Andre 通常情况下你是对的,但在我的特定情况下,我需要使用协议反射(用于NSXPCInterface)。 - Coder-256

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接