【问题标题】:Check if an object is an instance of class meta type in Swift [duplicate]检查对象是否是Swift中类元类型的实例[重复]
【发布时间】:2016-12-31 01:48:18
【问题描述】:

我有一个不同类型的对象数组和一个类型数组。对于每个对象,我想遍历类型数组并查看对象是否是该类型。像这样的:

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 和一些反射巫术以某种方式完成我想要的吗?

对不起,如果标题具有误导性 - 我理解得不够好,无法提出正确的问题。

【问题讨论】:

  • @Hamish:你的回答很棒!如果您在此处将其作为答案提交,我很乐意接受。
  • 很高兴您发现它很有用!在这种情况下可能会像一个骗子一样接近

标签: swift class reflection swift2 instance


【解决方案1】:

通过为每个类添加标题,您可以打开它们。另外,您是否考虑过使用协议而不是超类?

可能是这样的:

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)")
    }
}

【讨论】:

  • 我非常感谢您的回复,但不幸的是,这并没有达到我想要的效果。首先,使用字符串需要很多额外的开销来维护并且容易出错。该语言已经通过dynamicType 处理了所有这些(参见我上面的示例)。其次,您的示例不处理子/超类的情况:ChildB.title 没有证据表明它既是 ChildB Parent
猜你喜欢
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 2014-07-28
  • 2013-05-17
  • 2021-11-20
  • 1970-01-01
  • 2020-12-21
相关资源
最近更新 更多