Swift中Protocol与Polymorphism对比:面向编程新手的选型疑问
嘿,我刚入门面向对象编程的时候也纠结过这个问题,太懂这种“两种方法好像都能用,到底选哪个”的困惑了!先给你理清楚核心逻辑:Protocol其实是实现多态的一种方式,它们不是对立的,很多时候是配合使用的。下面我结合场景给你拆解什么时候该侧重用哪个:
先搞懂概念关联
- 多态是面向对象的核心特性,本质就是“同一个行为,不同对象有不同实现”——不管是通过继承父类重写方法,还是通过遵守协议实现方法,都是在做多态。
- Protocol(协议)是定义一套方法/属性的规范,让任何类(不管有没有继承关系)都能遵守并实现这套规范,属于接口式多态,重点是规范行为,不关心类的继承层级。
- **Delegate(委托)**是Protocol的典型应用场景,用来实现对象间的解耦通信——比如A让B帮忙处理某个事件,只要B遵守A定义的协议就行,不用A直接依赖B的具体类型。
具体选择场景
1. 当类之间没有继承关系,或者不想用继承时,选Protocol
举个例子:你有Dog、Car、Robot三个完全不相关的类,但都需要实现“发出声音”的功能。如果用继承,你得硬造一个SoundMaker父类让它们继承,但这显然不符合逻辑(狗、车、机器人怎么会是同一个父类的子类?)。
这时候用Protocol就特别优雅:
// 定义协议 protocol Soundable { func makeSound() } // 不同类分别遵守协议实现 class Dog: Soundable { func makeSound() { print("汪汪汪!") } } class Car: Soundable { func makeSound() { print("嘀嘀嘀!") } } class Robot: Soundable { func makeSound() { print("哔哔哔!") } }
这样既实现了“统一调用makeSound(),不同对象有不同表现”的多态,又避免了不合理的继承层级,代码更灵活。
2. 当类有共同父类且共享大部分逻辑时,选继承式多态
比如你有Cat、Dog、Bird,它们都是Animal的子类,大部分属性(age、weight)和方法(eat()、sleep())都一样,只有makeSound()的实现不同。
这时候继承Animal父类就更合适,因为可以复用父类的代码,不用每个类都重复写相同的逻辑:
class Animal { var age: Int init(age: Int) { self.age = age } func eat() { print("吃东西") } // 父类定义方法,子类重写(多态的体现) func makeSound() { fatalError("子类必须重写这个方法") } } class Dog: Animal { override func makeSound() { print("汪汪汪!") } } class Cat: Animal { override func makeSound() { print("喵喵喵!") } }
这种场景下,继承式多态能帮你减少重复代码,逻辑也更清晰。
3. 需要对象间解耦通信时,用Delegate(基于Protocol)
比如你写一个列表页面,自定义的TableViewCell想把点击事件传给ViewController,但又不想让Cell直接依赖ViewController的具体类型(不然Cell就没法复用在其他页面了)。
这时候就用Delegate模式:
// 定义委托协议 protocol TableCellDelegate: AnyObject { func cellDidTap(_ cell: CustomTableCell) } class CustomTableCell: UITableViewCell { // 委托对象,类型是协议 weak var delegate: TableCellDelegate? @IBAction func tapButton(_ sender: UIButton) { // 点击时通知委托 delegate?.cellDidTap(self) } } // ViewController遵守协议实现方法 class MyViewController: UIViewController, TableCellDelegate { func cellDidTap(_ cell: CustomTableCell) { print("Cell被点击了!") } // 给Cell设置委托 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomTableCell cell.delegate = self return cell } }
这里Delegate本质也是多态——任何遵守TableCellDelegate的对象都可以作为Cell的委托,完美实现了对象间的解耦。
总结一下
- 多态是你要达到的目标,Protocol是实现这个目标的工具之一(另一个是继承);
- 如果需要跨类的行为规范,或者不想用继承,优先选Protocol;
- 如果类有共享逻辑的继承层级,优先选继承式多态;
- Delegate是Protocol的具体用法,专门解决对象间的解耦通信问题。
内容的提问来源于stack exchange,提问作者Andrew Tuzson

