Тип проверки Swift на общий тип

У меня есть общая функция с 1 параметром и вы хотите проверить тип переданного параметра с общим типом. Что-то вроде этого:

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

Но я не знаю, как назвать это

generic<String>("Hello")

Дает мне ошибку компилятора: "Нельзя явно специализировать общую функцию Родовой ( "Hello" )

Ответ 1

Вы не можете указать функции, какие типы ее общих заполнителей (в отличие от общей структуры). Он должен вывести их из контекста, например. его аргументы.

Один из способов сделать то, что вы хотите, - добавить еще один аргумент, относящийся к типу 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

Точка дженериков состоит в том, чтобы работать с аргументами в общем случае, но вы не даете функции какой-либо аргумент определенного типа, на самом деле выполняющий какую-либо работу (следовательно, неспособность сделать вывод).

Ответ 2

Эта ситуация не является кандидатом на общий. Вы просто просите протестировать объект против типа. Если это всегда будет 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

Более общий подход:

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

Ответ 4

Проверка, является ли общий тип каким классом.

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