2

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

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

最后一条语句返回 false,type(of: <T>)显然返回对象的最终类。

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

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

这里两个语句都评估为真,因为is关键字显然是在考虑超类。但我不能这样做是比较两个对象的类型,如下所示:

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

我需要得到这样的结果:

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

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

4

3 回答 3

2

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

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
于 2020-11-23T18:46:42.057 回答
1

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

他们的医生说

Type.IsSubclassOf(Type)如果当前 Type 派生自 c,则该方法返回 true;否则为假。如果 c 和当前 Type 相等,此方法也返回 false。来源:微软文档

Swift 有类型检查操作 (is) 来检查一个实例是否属于某个子类类型,但true如果两者是相同的类型,它就会返回。这种行为使其不同于 .NetType.IsSubclassOf(Type)方法。资源

解决方案是开发一个在行为上与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")
}
于 2020-11-23T20:08:15.740 回答
0

is运算符需要 rhs(右侧)的类型,而不是实例/对象。

Swift 的约定是你不要以小写字母开头的类名。如果我按照约定重写你的代码,用类名替换对象类型,我会得到你期望的结果:

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

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

于 2020-11-23T19:39:56.237 回答