针对泛型类型的Swift检查类型

时间:2015-01-02 18:23:48

标签: swift

我有一个带有1个参数的泛型函数,想要检查传递参数的类型和泛型类型。像这样:

func generic<T>(parameter: AnyObject) -> Bool {
    if parameter is T {
        return true
    } else {
        return false
    }
}

但我不知道怎么称呼这个

generic<String>("Hello")

给我一​​个编译器错误:“无法明确地专门化泛型函数 通用的( “你好”)

4 个答案:

答案 0 :(得分:24)

您无法告诉函数其通用占位符的类型是什么(与通用结构不同)。它必须从上下文中推断它们,例如它的论点。

执行所需操作的一种方法是添加与类型T相关的另一个参数。您可以使用所需类型的元类型,而不是传入虚拟值:

func generic<T>(parameter: AnyObject, type: T.Type) -> Bool {
    if parameter is T {
        return true
    } else {
        return false
    }
}

let o: AnyObject = "hello"
generic(o, String.self)    // true
generic(o, NSString.self)  // also true
generic(o, Int.self)       // false

但是,我会问你,你认为你在这里取得了什么成就?除了将is实现为函数之外,您基本上没有做任何事情:

o is String     // true
o is NSString   // true
o is Int        // false

泛型的观点是通常对参数进行操作,但是你没有给函数任何特定类型的参数实际做任何工作(因此无法推断)。

答案 1 :(得分:10)

检查泛型类型是否属于哪个类。

protocol Some {}
class SomeClass: Some {}
class AClass: Some {}
func test(_ t: T) -> String {
    if T.self == SomeClass.self {
        return "Some Class"
    } else {
        return "Another Class"
    }
}

print(test(SomeClass())) // Some Class
print(test(AClass())) // Another Class

答案 2 :(得分:3)

这种情况不是通用的候选者。您只是要求针对类型测试对象。如果这总是AnyObject,你可以尝试这样的事情:

func istest(parameter: AnyObject, whattype: AnyObject.Type) -> Bool {
    if parameter.dynamicType === whattype.self {
        return true
    } else {
        return false
    }
}

如果你真的想要一个可以专门化的泛型,你不能明确地专门化一个函数,所以你必须将你的函数包装成泛型类型并专门化:

struct Generic<T> {
    func generic(parameter: AnyObject) -> Bool {
        if parameter is T {
            return true
        } else {
            return false
        }
    }
}

let ok = Generic<String>().generic("howdy")
let ok2 = Generic<Int>().generic(1)

但是,正如我已经说过的那样,你给出的例子不是一个很好的候选人。请记住,泛型在编译时被解析 - 我们已经知道解析类型将是什么。因此,您的测试毫无意义,因为您已经知道了答案。这就是为什么我向你展示了一个替代函数,其中值和类型都是未知的。

答案 3 :(得分:1)

更通用的方法:

struct Asserter<T>{
    func generic(_ val:Any) -> Bool{
        let type = type(of: val)
        return T.self == type
    }
}
_ = Asserter<String>().generic(2)//false
_ = Asserter<String>().generic("")//true