2016-08-24 4 views
4

У меня есть массив объектов различных типов и массив типов. Для каждого объекта я хотел бы перебирать массив типов и видеть, является ли объект таким типом. Что-то вроде этого:Проверьте, является ли объект экземпляром класса meta в Swift

class Parent {} 
class ChildA: Parent {} 
class ChildB: Parent {} 
class GrandChildA: ChildA {} 

var objects: [Any] = ["foo", ChildA(), ChildA(), ChildB(), GrandChildA()] 
var classes = [Parent, ChildA, ChildB] // This line doesn't compile!! 

for obj in objects { 
    for cls in classes { 
     if obj is cls { 
      NSLog("obj matches type!") 
     } 
    } 
} 

Это не работает, потому что вы не можете хранить классы в массиве. Как я понимаю, вы магазин тазов типа класса, такие как ChildA.self:

ChildA().dynamicType == ChildA.self // true 

Но это не ручка подклассы:

ChildA().dynamicType == Parent.self // false 

Очевидно, оператор is решает случай подкласса:

ChildA() is Parent // true 

Но если я хочу использовать is, я не знаю, как хранить типы классов в массиве.

Могу ли я выполнить то, что я хочу, используя Swift и некоторое отражение вуду?

Извините, если заголовок вводит в заблуждение - я не понимаю этого достаточно хорошо, чтобы сформировать правильный вопрос.

+1

Сравнить https://stackoverflow.com/ q/44874126/2976878 – Hamish

+0

@ Хамиш: Ваш ответ велик! Если вы представите его в качестве ответа здесь, я был бы рад принять его. –

+0

Рад, что вы сочли это полезным! Может быть, так же близок как обман в этом случае – Hamish

ответ

-2

Добавив заголовок для каждого класса, вы можете включить его. Кроме того, вы думали использовать протокол вместо суперкласса?

Может быть что-то вроде этого:

protocol Parentable { 
    var title : String { get set } 
} 

class ChildA : Parentable{ 
    var title: String 
    init() { 
     self.title = "ChildA" 
    } 
    init(title: String){ 
     self.title = title 
    } 
} 
class ChildB: Parentable { 
    var title: String 
    init(){ 
     self.title = "ChildB" 
    } 
} 
class GrandChildA: ChildA { 
    override init() { 
     super.init(title: "GrandChild") 
    } 
} 

var objects: [Parentable] = [ChildA(), ChildA(), ChildB(), GrandChildA()] 

for obj in objects { 
    switch obj.title { 
    case "ChildA": 
     print("Object is of type \(obj.title)") 
    case "ChildB": 
     print("Object is of type \(obj.title)") 
    case "GrandChild": 
     print("Object is of type \(obj.title)") 
    default : 
     print("Object is of type \(obj.title)") 
    } 
} 

Вы также можете сделать это с суперкласса, как это, если вам нужны объекты, переданные по ссылке:

class Parent { 
    var title: String 

    init() { 
     self.title = "Parent" 
    } 
    init(title: String) { 
     self.title = title 
    } 
} 
class ChildA: Parent { 
    override init() { 
     super.init(title: "ChildA") 
    } 
    override init(title: String) { 
     super.init(title: title) 
    } 
} 
class ChildB: Parent { 
    override init() { 
     super.init(title: "ChildB") 
    } 
} 
class GrandChildA: ChildA { 
    override init() { 
     super.init(title: "GrandChild") 
    } 
} 

    var objects: [Parent] = [ChildA(), ChildA(), ChildB(), GrandChildA()] 

    for obj in objects { 
     switch obj.title { 
     case "ChildA": 
      print("Object is of type \(obj.title)") 
     case "ChildB": 
      print("Object is of type \(obj.title)") 
     case "GrandChild": 
      print("Object is of type \(obj.title)") 
     default : 
      print("Object is of type \(obj.title)") 
    } 
} 
+1

Я очень ценю ответ, но, к сожалению, это не выполняет то, что я хочу. Во-первых, использование строк требует много дополнительных накладных расходов для меня, чтобы поддерживать и подвержен ошибкам. Язык уже обрабатывает все это через '' 'dynamicType''' (см. Мой пример выше). Во-вторых, ваш пример не обрабатывает случай суб/суперклассов: '' 'ChildB.title''' не дает мне никаких доказательств того, что это и' '' ChildB''' * и * a '' 'Parent'' '. –

Смежные вопросы