Можете ли вы проверить, является ли тип (не экземпляр) подклассом другого типа? - PullRequest
2 голосов
/ 21 января 2020

Учитывая этот код ...

class Vehicle{}

class Car : Vehicle {}

class Honda : Car {}

Как бы вы написали функцию 'findFirst' ниже ...

class TypeManager {

    var managedTypes:[Any.Type]?

    func findFirst(_ type:Any.Type) -> Any.Type? {
        return managedTypes.first{ t in t is type.Type } // <-- Doesn't like 'type'
    }
}

var typeManager = TypeManager()
typeManager.managedTypes = [
    String.self,
    Int.self,
    Honda.self
]

let firstCarType = typeManager.findFirst(Car.Type)

Примечание: на самом деле выполняется обратный ключ поиск по словарю. В идеальном решении я сначала попытался бы найти точное совпадение с типом, а если не нашел, согласился на подкласс типа. Я просто упростил (фальшивый) код, чтобы сосредоточиться на соответствующей части.

Ответы [ 2 ]

1 голос
/ 22 января 2020

Классы являются экземплярами мета-типа и могут быть проверены с помощью is и as?. Вы можете использовать функцию generi c для передачи искомого типа:

class TypeManager {

    var managedTypes:[Any.Type] = []

    func findFirst<T>(_: T.Type) -> Any.Type? {
        return managedTypes.first { $0 is T.Type }
    }
}

Пример:

if let firstCarType = typeManager.findFirst(Car.self) {
    print(firstCarType) // Honda
}

Или с условным связыванием и compactMap:

class TypeManager {

    var managedTypes:[Any.Type] = []

    func findFirst<T>(_: T.Type) -> T.Type? {
        return managedTypes.compactMap { $0 as? T.Type }.first
    }
}

Преимущество в том, что возвращаемый тип - T.Type?, а не Any.Type?. (Используйте managedTypes.lazy.compactMap, если список может быть большим и требуется короткое замыкание.)

1 голос
/ 22 января 2020

Чтобы раскрыть отличный ответ Мартина Р. , вы можете сделать расширение массива следующим образом:

extension Array {
    func first<T>(ofType: T.Type) -> T.Type?  {
        return first { $0 is T.Type } as? T.Type
    }
    func first<T>(ofExactType type: T.Type) -> T.Type? {
        return first { $0 as? Any.Type == type } as? T.Type
    }
}

class Vehicle {}
class Car : Vehicle {}
class Honda: Car {}

let carTypes = [Honda.self, Vehicle.self, Car.self] // Inferred type [Vehicle]
print(carTypes.first(ofType: Car.self) ?? "n/a") // prints Honda
print(carTypes.first(ofExactType: Car.self) ?? "n/a") // prints Car

Кроме того, только FYI, $0 as? Any.Type == type - то же самое, что и $0 as? Any.Type == T.self. Либо один будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...