实现Fly与Swim协议的Bird类中同名speed属性的区分问题
Swift协议同名属性冲突问题解答
代码示例
protocol Fly { var speed: Int { get set } } protocol Swim { var speed: Int { get set } } class Bird: Fly, Swim { var speed: Int = 0 // 这个属性属于Fly还是Swim? }
问题解答
a) 保留属性同名时如何区分两个speed属性?
需要用显式协议成员实现的语法,给每个协议的speed单独实现逻辑,内部用不同的存储属性分别存储飞行速度和游动速度。示例代码如下:
class Bird: Fly, Swim { // 内部存储飞行速度 private var _flySpeed: Int = 0 // 显式实现Fly协议的speed属性 var Fly.speed: Int { get { _flySpeed } set { _flySpeed = newValue } } // 内部存储游动速度 private var _swimSpeed: Int = 0 // 显式实现Swim协议的speed属性 var Swim.speed: Int { get { _swimSpeed } set { _swimSpeed = newValue } } }
通过协议名.属性名的方式,就能明确区分两个协议的同名属性,各自对应独立的存储值。
b) 当前代码片段中Bird类的speed属性对应哪个协议?
当前代码里的speed属性同时满足两个协议的要求,并没有专门对应某一个协议。也就是说,把Bird实例转为Fly类型访问speed,或者转为Swim类型访问speed,拿到的都是同一个值——这显然不符合需求,因为飞行和游动速度应该是独立的。
c) 如何分别获取飞行速度与游动速度?
基于上面的显式协议实现代码,有两种规范的获取方式:
- 将实例强制转换为对应的协议类型后访问
speed:
let bird = Bird() // 设置并获取飞行速度 (bird as Fly).speed = 100 let flySpeed = (bird as Fly).speed // 设置并获取游动速度 (bird as Swim).speed = 20 let swimSpeed = (bird as Swim).speed
- 如果内部的存储属性(比如
_flySpeed、_swimSpeed)被设为公开的,也可以直接访问,但更推荐第一种方式,符合协议的抽象设计原则。
内容的提问来源于stack exchange,提问作者Kanishka
相关产品推荐
相关产品推荐

