简体   繁体   中英

Swift check type against a generic type

I've a generic function with 1 parameter and want to check the type of the passed parameter with the generic type. Something like this:

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

But I don't know how to call this

generic<String>("Hello")

Gives me a compiler error: "Cannot explicitly specialize a generic function generic("Hello")

You cannot tell a function what the types of its generic placeholders are (unlike with a generic struct). It must infer them from the context eg its arguments.

One way to do what you want is to add another argument related to type T . Rather than pass in a dummy value, you could use the metatype of the type you want:

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

However, I would ask you, what is it you think you're achieving here? You've essentially done nothing more than implement is as a function:

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

The point of generics is to operate on arguments generically, but you aren't giving the function any argument of a specific type to actually do any work on (hence the inability to infer one).

Checking if generic type is which class.

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

This situation is not a candidate for a generic. You are just asking to test an object against a type. If this is always going to be an AnyObject, you might try something like this:

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

If you really want a generic that you can specialize, you cannot specialize a function explicitly, so you will have to wrap your function in a generic type and specialize that:

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)

But the example you have given, as I've already said, is not a good candidate for doing that. Remember, a generic is resolved at compile time - we already know what the resolved type is going to be. Thus, your test is pointless because you already know the answer. That is why I showed you an alternative function where the value and the type are both unknown.

A more generic approach:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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