Swift - 检查两个对象是否属于同一类型或超类类型

Swift - check if two objects are of same type or superclass-type

我想检查两个对象是否属于 - 或者属于 - 同一个超级class。

class myClass {}
class mySubclass: myClass {}

let myObject = myClass()
let myOtherObject = myClass()
let mySubclassedObject = mySubclass()

我知道我可以这样检查类型:

type(of: myObject) == myClass.self                // true
type(of: myObject) == type(of: myOtherObject)     // true

type(of: mySubclassedObject) == myClass.self      // false

最后的说法returns为假,因为type(of: <T>)显然returns对象的最终class.

类型检查的另一种方法是 is 关键字:

mySubclassedObject is mySubclass     // true
mySubclassedObject is myClass        // true 

此处两个语句的计算结果均为真,因为 is 关键字显然考虑了 superclass。但是我不能那样做的是像这样比较两个对象的类型:

myOtherObject is myObject   // Use of undeclared type 'myObject'

我需要得到这样的结果:

myObject is myOtherObject        // true 
mySubclassedObject is myObject   // true
myObject is mySubclassedObject   // false

我希望找到类似 .isSubclassOf 的东西,但在 Swift 中似乎找不到。那么我怎样才能得到我想要的结果呢?

一种方法可能是尝试这样的泛型

func isObject<P>(_ object: Any, ofType other: P) -> Bool {
    object is P
}

isObject(myObject, ofType: myOtherObject)           //true
isObject(mySubclassedObject, ofType: myObject)      //true
isObject(myObject, ofType: mySubclassedObject)      //false

is 运算符需要右手边的类型(右侧),而不是 instance/object。

Swift 惯例是 class 名称不能以小写字母开头。如果我按照惯例重写您的代码,将对象类型替换为 class 名称,我将得到您期望的结果:

class MyClass {}
class MySubclass: MyClass {}

let myObject = MyClass()
let myOtherObject = MyClass()
let mySubclassedObject = MySubclass()

type(of: myObject) == MyClass.self                // true
type(of: myObject) == type(of: myOtherObject)     // true

type(of: mySubclassedObject) == MyClass.self      // false

mySubclassedObject is MySubclass     // true
mySubclassedObject is MyClass        // true

myOtherObject is MyClass

myObject is MyClass        // true
mySubclassedObject is MyClass   // true
myObject is MySubclass   // false

is 运算符需要 rhs 上的类型,而不是对象。

我想您问的是与 .Net 平台上的 Type.IsSubclassOf(Type) 相同的功能

他们的医生说

the method Type.IsSubclassOf(Type) return true if the current Type derives from c; otherwise, false. This method also returns false if c and the current Type are equal. source: microsoft doc

Swift 具有类型检查操作(是)以检查实例是否属于某个子类类型,但它 returns true 如果两者是同一类型。此行为使其不同于 .Net Type.IsSubclassOf(Type) 方法。 source

解决方案是开发一个行为类似于 Type.IsSubclassOf(Type) 的自定义函数。

Any、AnyClass 和 AnyObject 不能有扩展,因此创建全局函数的最佳方法:

func type<T: AnyObject >(_ object: AnyObject, isSubclassOf toto: T) -> Bool {
    if object is T {
        if Swift.type(of: object) === Swift.type(of: myOtherObject) {
            return false
        } else {
            return true
        }
    } else {
        return false
    }
}

以上函数将通过以下测试:

// MARK: - --- UnitTests ---
import XCTest

class TypeIsSubclassOfTests: XCTestCase {
    func testSubclass() {
        XCTAssertFalse(type(myObject, isSubclassOf: myOtherObject))
        XCTAssertFalse(type(myOtherObject, isSubclassOf: myObject))
        XCTAssertTrue(type(mySubclassedObject, isSubclassOf: myObject))
        XCTAssertFalse(type(myObject, isSubclassOf: mySubclassedObject))
    }
}

该函数的用法如下:

if type(object1, isSubclassOf: object2) {
    debugPrint("object1 is a class which subclass from object2 class")
} else {
    debugPrint("object1 is the same class as object2 or is not a subclass of object2 class")
}