如何使用'is'在Swift中进行参照类型比较?

时间:2015-03-30 15:20:02

标签: swift

如果右侧是引用而不是硬编码类型,我无法弄清楚如何使用is运算符在Swift中进行类型比较。

例如,

class GmBuilding { }
class GmOffice: GmBuilding { }
class GmFactory: GmBuilding { }

class GmStreet {
    var buildings: [GmBuilding] = []
    func findAllBuildingsOfType(buildingType: GmBuilding.Type) -> [GmBuilding] {
        var result: [GmBuilding] = []
        for building in self.buildings {
            if building is buildingType { // complains that buildingType is not a type
                result.append(building)
            }
        }
        return result
    }
}

let myStreet = GmStreet()
var buildingList: [GmBuilding] = myStreet.findAllBuildingsOfType(GmOffice.self)

它抱怨建筑类型不是类型'。如何才能工作?

4 个答案:

答案 0 :(得分:3)

通用方法可以做你想做的事:

func findAllBuildingsOfType<T: GmBuilding>(buildingType: T.Type) -> [GmBuilding] {
    // you can use `filter` instead of  var/for/append
    return buildings.filter { $0 is T }
}

只要您确实只想在编译时确定类型,这将有效:

let myStreet = GmStreet()
let buildingList = myStreet.findAllBuildingsOfType(GmOffice.self)
//   T is set at compile time to GmOffice  --------^

但是,通常在出现此问题时,后续问题是,如何将GmOffice.self存储在变量中,然后在运行时确定类型?并且 将无法使用此技术。但是如果在编译时静态修复类型对你来说足够了,那就应该这样做。

答案 1 :(得分:2)

如果AirSpeed Velocity的答案对您不起作用,您也可以通过桥接到Objective-C来实现这一目标。

GmBuilding继承自NSObject

class GmBuilding: NSObject { }

并使用isKindOfClass(_:)检查类型:

for building in self.buildings {
    if building.isKindOfClass(buildingType) {
        result.append(building)
    }
}

不是很好,但它确实有效。

答案 2 :(得分:0)

我确信必须有比这更好的方法,但它不需要从NSObject继承并且它在运行时工作 - 根据我的操场

class GmBuilding { }
class GmOffice: GmBuilding { }
class GmFactory: GmBuilding { }

func thingIs(thing: GmBuilding, #sameTypeAs: GmBuilding) -> Bool
{
    return thing.dynamicType === sameTypeAs.dynamicType
}


var foo: GmOffice = GmOffice()

thingIs(foo, sameTypeAs: GmOffice()) // true
thingIs(foo, sameTypeAs: GmFactory()) // false

我实例化一个对象的主要原因(你可以使用单例)是因为我无法弄清楚如何将参数声明为元类型。

它也不适用于

thingIs(foo, sameTypeAs: GmBuilding()) // false :=(

答案 3 :(得分:0)

作为最后的手段,使用Obj-C反映功能:

import ObjectiveC

func isinstance(instance: AnyObject, cls: AnyClass) -> Bool {
    var c: AnyClass? = instance.dynamicType
    do {
        if c === cls {
            return true
        }
        c = class_getSuperclass(c)
    } while c != nil
    return false
}

class GmBuilding { }
class GmOffice: GmBuilding { }
class GmFactory: GmBuilding { }

isinstance(GmOffice(), GmOffice.self) // -> true
isinstance(GmOffice(), GmFactory.self) // -> false
isinstance(GmOffice(), GmBuilding.self) // -> true