如何无需as?运算符遍历Animal协议数组并调用对应方法?
不用
as?的简洁实现方案 方案1:给协议加统一方法,让各类型自己实现对应行为
其实bark()和meow()说白了都是“发出叫声”,直接在Animal协议里定义一个统一的方法(比如makeSound()),让Dog和Cat各自实现这个方法就行。遍历数组的时候直接调用统一方法,完全不用判断类型:
protocol Animal { func makeSound() } struct Dog: Animal { func makeSound() { print("Woof!") // 对应原来的bark() } } struct Cat: Animal { func makeSound() { print("Meow!") // 对应原来的meow() } } // 调用示例 let animals: [Animal] = [Dog(), Cat(), Dog()] for animal in animals { animal.makeSound() }
这是最符合Swift面向协议编程思路的写法,后续加新动物(比如Bird),只要遵守协议实现makeSound()就行,根本不用改遍历的代码。
方案2:协议扩展封装类型判断逻辑
要是不想改原来的bark()和meow()方法名,可以给Animal协议加个扩展,内部用switch做类型匹配(Swift里switch能直接匹配协议的实现类型,不用as?),把判断逻辑封装起来:
protocol Animal {} struct Dog: Animal { func bark() { print("Woof!") } } struct Cat: Animal { func meow() { print("Meow!") } } // 扩展协议,统一调用入口 extension Animal { func performSound() { switch self { case let dog as Dog: dog.bark() case let cat as Cat: cat.meow() default: print("Unknown sound") } } } // 调用示例 let animals: [Animal] = [Dog(), Cat(), Dog()] for animal in animals { animal.performSound() }
这里虽然用到了as,但属于模式匹配的语法,比在循环里挨个用as?判断清爽多了,把脏活累活都封装在扩展里,调用方代码干净得很。
方案3:用枚举替代协议(适合类型固定的场景)
如果你的动物类型不会频繁新增,直接用枚举+关联值的方式代替协议更简单,遍历的时候直接switch枚举值,连类型转换都不用:
enum Animal { case dog case cat func makeSound() { switch self { case .dog: print("Woof!") case .cat: print("Meow!") } } } // 要是需要给动物加属性,用关联值就行: // enum Animal { // case dog(name: String) // case cat(age: Int) // } // 调用示例 let animals: [Animal] = [.dog, .cat, .dog] for animal in animals { animal.makeSound() }
这种写法更轻量,没有协议和结构体的层级,逻辑直接明了,适合类型固定的场景。
内容的提问来源于stack exchange,提问作者neuraldag
相关产品推荐
相关产品推荐

