Swift协议与扩展:方法调用时机解析及代码示例求助
嘿,我来帮你理清楚Swift里协议和扩展中方法的调用逻辑,还有你提到的那段代码~
Swift协议与扩展中方法的调用时机
得先明确两种核心场景,这直接决定了代码会调用哪个版本的方法:
1. 协议已声明的方法,扩展提供默认实现
- 如果某个方法在协议里已经明确声明,哪怕扩展给了它默认实现,当你用协议类型的变量/常量调用这个方法时,会优先执行实现该协议的结构体/类的自定义实现,而不是扩展里的默认版本。
- 这是因为协议声明的方法会走动态派发,Swift会在运行时判断实际的类型,调用对应的实现。
2. 扩展新增的、协议未声明的方法
- 如果方法只在扩展里定义,协议本身没有声明它,那么不管实现类有没有重写这个方法,当你用协议类型的变量/常量调用时,都会执行扩展里的默认实现。
- 这类方法是静态派发的,编译时就确定了调用的版本,不会去匹配实现类的重写逻辑。
解释给定的协议与扩展代码
先把你给出的不完整代码补全成合理的完整版本:
struct Pizza { let ingredients: [String] } protocol Pizzeria { func makePizza(ingredients: [String]) -> Pizza // 注意:这里注释掉了 makeMargherita 的协议声明 } extension Pizzeria { func makeMargherita() -> Pizza { return makePizza(ingredients: ["tomato", "mozzarella"]) } } struct Lombardis: Pizzeria { func makePizza(ingredients: [String]) -> Pizza { return Pizza(ingredients: ingredients) } // Lombardis 自定义重写了 makeMargherita 方法 func makeMargherita() -> Pizza { return makePizza(ingredients: ["tomato", "mozzarella", "basil"]) } }
现在拆解这段代码的逻辑:
1. 核心结构说明
Pizza:简单的结构体,用来存储披萨的配料列表。Pizzeria:协议,要求所有遵循它的类型必须实现makePizza(ingredients:)方法,但没有把makeMargherita()纳入协议要求。Pizzeria的扩展:给所有遵循该协议的类型提供了makeMargherita()的默认实现——调用协议要求的makePizza方法,制作经典的玛格丽特披萨(番茄+马苏里拉)。Lombardis:遵循Pizzeria的结构体,不仅实现了协议要求的makePizza方法,还自己重写了makeMargherita,做了一款加罗勒的定制版玛格丽特。
2. 不同调用场景的行为差异
场景一:用具体类型(Lombardis)调用
let myPizzeria = Lombardis() let pizza = myPizzeria.makeMargherita() // 这里会调用 Lombardis 自己重写的版本,得到带罗勒的玛格丽特披萨
因为变量是明确的Lombardis类型,Swift直接调用该类型的方法实现。
场景二:用协议类型(Pizzeria)调用
let myPizzeria: Pizzeria = Lombardis() let pizza = myPizzeria.makeMargherita() // 这里会调用扩展里的默认版本,得到只有番茄+马苏里拉的披萨
原因是makeMargherita()没有在Pizzeria协议里声明,属于扩展新增的方法,所以当变量是协议类型时,会执行扩展的默认实现,哪怕Lombardis重写了它。
如果把协议里的makeMargherita()注释去掉呢?
如果修改协议,把makeMargherita()纳入协议要求:
protocol Pizzeria { func makePizza(ingredients: [String]) -> Pizza func makeMargherita() -> Pizza // 取消注释,加入协议声明 }
这时候再用协议类型调用:
let myPizzeria: Pizzeria = Lombardis() let pizza = myPizzeria.makeMargherita() // 现在会调用 Lombardis 的重写版本,因为方法在协议里声明了,走动态派发
内容的提问来源于stack exchange,提问作者PruitIgoe
相关产品推荐
相关产品推荐

