Swift 中我们虽然可以通过 dynamicType
来获取一个对象的动态类型 (也就是运行时的实际类型,而非代码指定或编译器看到的类型)。但是在使用中,Swift 现在却是不支持多方法的,也就是说,不能根据对象在动态时的类型进行合适的重载方法调用。
举个例子来说,在 Swift 里我们可以重载同样名字的方法,而只需要保证参数类型不同:
class Pet {}
class Cat: Pet {}
class Dog: Pet {}
func printPet(pet: Pet) {
print("Pet")
}
func printPet(cat: Cat) {
print("Meow")
}
func printPet(dog: Dog) {
print("Bark")
}
在对这些方法进行调用时,编译器将帮助我们找到最精确的匹配:
printPet(Cat()) // Meow
printPet(Dog()) // Bark
printPet(Pet()) // Pet
对于 Cat
或者 Dog
的实例,总是会寻找最合适的方法,而不会去调用一个通用的父类 Pet
的方法。这一切的行为都是发生在编译时的,如果我们写了下面这样的代码:
func printThem(pet: Pet, _ cat: Cat) {
printPet(pet)
printPet(cat)
}
printThem(Dog(), Cat())
// 输出:
// Pet
// Meow
打印时的 Dog()
的类型信息并没有被用来在运行时选择合适的 printPet(dog: Dog)
版本的方法,而是被忽略掉,并采用了编译期间决定的 Pet
版本的方法。因为 Swift 默认情况下是不采用动态派发的,因此方法的调用只能在编译时决定。
要想绕过这个限制,我们可能需要进行通过对输入类型做判断和转换:
func printThem(pet: Pet, _ cat: Cat) {
if let aCat = pet as? Cat {
printPet(aCat)
} else if let aDog = pet as? Dog {
printPet(aDog)
}
printPet(cat)
}
// 输出:
// Bark
// Meow