面向协议编程与面向对象编程的区别与范例
问题描述:
最近我遇到了面向协议的编程(WWDC 2015),它确实很吸引人,但它却是一个非常难以驯服并将其付诸实践的概念。所以我在互联网上做了一些研究,并发现了这个代码。它的模型玩家和敌人在一个典型的游戏场景,玩家可以装备的武器和射击的敌人,那么敌人随后受到伤害:面向协议编程与面向对象编程的区别与范例
protocol Targetable {
var life: Int { get set }
func takeDamage(damage: Int)
}
protocol Shootable {
func shoot(target: Targetable)
}
class Pistol: Shootable {
func shoot(target: Targetable) {
target.takeDamage(1)
}
}
class Shotgun: Shootable {
func shoot(target: Targetable) {
target.takeDamage(5)
}
}
class Enemy: Targetable {
var life: Int = 10
func takeDamage(damage: Int) {
life -= damage
println("enemy lost \(damage) hit points")
if life <= 0 {
println("enemy is dead now")
}
}
}
class Player {
var weapon: Shootable!
init(weapon: Shootable) {
self.weapon = weapon
}
func shoot(target: Targetable) {
weapon.shoot(target)
}
}
var terminator = Player(weapon: Pistol())
var enemy = Enemy()
terminator.shoot(enemy)
//> enemy lost 1 hit points
对我来说,这使得有很大的意义。但是,在我的内心深处,我对自己说“是啊,这个道理,但如果我要实现这样的事情,这将是完全不同的”,我也这样做:
class Gun {
var damage: Int {
return 0
}
}
class Pistol: Gun {
override var damage: Int {
return 5
}
}
class Shotgun: Gun {
override var damage: Int {
return 10
}
}
class Enemy {
var health = 100
func takeDamage(damage: Int) {
health = health - damage
print("Current health is: \(health)")
}
init(health: Int) {
self.health = health
}
}
class Player {
var gun: Gun
func shoot(enemy: Enemy) {
enemy.takeDamage(damage: gun.damage)
}
init(gun: Gun) {
self.gun = gun
}
}
let player = Player(gun: Pistol())
let enemy = Enemy(health: 100)
player.shoot(enemy: enemy)
//Current health is: 95
他们俩模型共享相同的损害承担机制,你有一种方法是协议和对象的混合,另一方面你有纯粹的对象。有很多人能告诉我哪种方法最好,为什么?
谢谢!
答
哪个更好是主观问题,据我所知在本网站上不鼓励。然而,第一个更符合Swift社区最近推荐的“协议导向”成语。
然而,关于你的第二个例子的一件事是你的Gun
超类除了定义一个接口之外没有什么其他的功能;它自己的实现damage
从来没有实际使用过。因此,在这种情况下,协议当然似乎是正确的方法。
答
POP的优点之一是类/结构可以采用多个协议,而类只能是一个超类的子类。如果您想要一个球员,也可以shooted(敌人或者其他玩家),你只需要做出Player类,以符合可指定协议
class Player: Targetable { ... }
其次,一旦你使用一个协议如上面的例子类型,该类型的变量可以是任何符合本协议的类的实例。 在上面的例子和现实世界中,玩家的武器可以是猎枪或手枪,并且可以在任何时候改变。
var terminator = Player(life: 100, weapon: Pistol())
var enemy = Enemy()
terminator.shoot(enemy)
//> enemy lost 1 hit points
terminator.weapon = Shotgun()
terminator.shoot(enemy)
//> enemy lost 5 hit points
他们只是几个点来展示POP的优点,应该有更多的具体情况。
嘿,Crusty,再看那个视频。他们并不是说你不能在OOP中提出表示(特别是对于你在这里所拥有的简单的东西),但他们正在展示POP方法的优点。有很多原因可能会导致POP。也许价值语义。或者想象你有“猎人”(有“武器”)和另一个“猎杀”(有“健康”)。那么如果你介绍一个既是“猎人”又是“追捕”的新课程呢?你打算如何表现? POP中的平凡和自然,但在面向对象中卷积。 – Rob
POP是OOP的一部分。使用Swift的事情是协议(接口)不仅可以通过类来实现,还可以通过结构和枚举来实现。您将使用哪种方法还取决于特定情况。 –
我强烈建议你观看[this](https://www.youtube.com/watch?v=AySlYrel7fc)视频。对我来说,WWDC很难实现,用例可能不是那么多...... – Honey