2017-08-31 1 views
0

最近、私はプロトコル指向プログラミング(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 

同じ損害賠償メカニズムを共有している場合は、プロトコルとオブジェクトが混在するアプローチがあります。一方、純粋なオブジェクトがあります。多くの人が最高のアプローチとその理由を教えてくれますか?

ありがとうございます!

+0

こんにちは、Crusty、そのビデオをもう一度見てください。彼らはあなたがOOPの表現を思いつくことができないと言っているわけではありませんが(特にあなたがここにあるものほどシンプルなもの)、POPアプローチのメリットを示しています。 POPが必要な理由はたくさんあります。おそらく価値の意味論。または、「ハンター」(「武器」)と「狩猟」(「健康」)のクラスがあるとします。 「ハンター」と「ハンティング」の両方の新しいクラスを導入するとどうなりますか?どのようにそれを表現するつもりですか?軽薄で自然なPOPであるが、OOPでは複雑である。 – Rob

+0

POPはOOPの一部です。 Swiftとの違いは、プロトコル(インタフェース)はクラスだけでなく、構造体や列挙型でも実装できることです。どのアプローチを使用するかは、特定の状況によっても異なります。 –

+0

[this](https://www.youtube.com/watch?v=AySlYrel7fc)の動画を視聴することを強くおすすめします。私にとってWWDCは実現するのが難しく、ケースを使用するのはそれほど難しくないかもしれません... – Honey

答えて

2

これは私の知る限り、このサイトでは推奨されない主観的な質問です。しかし、最初のものは遅くにSwiftコミュニティによって推薦された "プロトコル指向"のイディオムの中にもっと収まります。

しかし、2番目の例では、Gunスーパークラスがインターフェイスを定義する以外に多くのことをしていないということがあります。 damageの独自の実装は決して実際には使用されません。したがって、プロトコルは確かにこの場合に正しいアプローチと思われます。

0

POPの利点の1つは、クラス/構造体が複数のプロトコルを採用できるということですが、クラスはただ1つのスーパークラスのサブクラスになる可能性があります。あなたはプロトコルとしてを使用したら、プレーヤーはまた、あなただけの、ターゲッティングプロトコルに

class Player: Targetable { ... } 

セカンドを適合するプレイヤークラスを作成する必要があります(敵や他のプレイヤーによって)shootedできることをしたい場合は、上記の例では、型、その型の変数は、このプロトコルに準拠する任意のクラスのインスタンスにすることができます。 上記の例と実際の世界では、プレーヤーの武器はショットガンまたはピストルになることができ、いつでも変更することができます。

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のメリットを示すにはほんの数ポイントですが、より具体的なケースではもっと多くのものが必要です。

関連する問題