确定通用(可能协议)类型的协议一致性

时间:2015-07-18 18:18:51

标签: swift generics protocols

是否可以在Swift中检查泛型类型是否符合协议,即使泛型类型是协议本身

protocol Parent {}
protocol Child: Parent {}
struct ParentType: Parent {}
struct ChildType: Child {}

func generic<T>(possiblyParent: T?) {
    if T.self is Parent.Type { //Only works for non-protocol types :(
        print("Parameter conforms to Parent.")
    }
}

let one: Parent? = nil
let two: Child? = nil
let three: ParentType? = nil
let four: ChildType? = nil

generic(one) //no, but I wish yes
generic(two) //no, but I wish yes
generic(three) //yes
generic(four) //yes

2 个答案:

答案 0 :(得分:0)

来自The Swift Programming Guide: Types

  

协议类型的元类型 - 不符合的具体类型   运行时的协议 - 是后面的协议的名称   .Protocol。例如,类类型SomeClass的元类型是   SomeClass.Type和协议SomeProtocol的元类型是   SomeProtocol.Protocol

将此问题应用于您的问题,您可以:

func generic<T>(possiblyParent: T?) {
    guard let p = possiblyParent else { return }

    // You could use an if statement instead of a switch here, if you wanted.
    switch p.dynamicType {
        case is Parent.Type, is Parent.Protocol:
            print("Parameter conforms to Parent.")
        default:
            print("Parameter doesn't conform to Parent")
    }
}

用法:

let one  : Parent = ParentType()
let two  : Child  = ChildType()
let three: Parent = ChildType()

generic(one)     // Prints: Parameter conforms to Parent.
generic(two)     // Prints: Parameter conforms to Parent.
generic(three)   // Prints: Parameter conforms to Parent.
generic("Hello") // Prints: Parameter doesn't conforms to Parent.

答案 1 :(得分:0)

您可以尝试使用标准的可选演员:

func generic<T>(possiblyParent: T?) {
    if let _ = possiblyParent as? Optional<Parent> {
        print("Parameter conforms to Parent.")
    }
}

在Swift 2.0 b3上,当您传递的选项不是nil时,它似乎正常工作。

但不幸的是:

let someInt: Int? = 3  // no and it is correct
let nilInt: Int? = nil // yes, but it should be no

这可能是一个错误。无论如何,如果possiblyParent为零,通常你可以用它做更多的事情。

因此,如果您的目的是在非空时实际使用该参数,您可能更喜欢这样的通用函数:

func generic<T>(possiblyParent: T?) {
    if let p = possiblyParent, // parameter is not empty
    let parent = p as? Parent  // parameter content conforms to Parent {
        print("parent can be safely used as a Parent.")
    }
}

希望这有帮助