オブジェクト指向とは?

2023/11/07に公開

オブジェクト指向について

https://youtu.be/7_hNvwSYEmo?si=sXHSWRu8GDqHH2kO
下記から内容を言語化していきますが、動画の内容から持ってきているため、より内容を確認したい方は動画の視聴をお願いしやす。

  • 内容
    動画を参考に、以下の内容を、まずはoopなしにやってみる。
最終出力(ゴール)
"ピカチュウがあらわれた。 ピカチュウのHPは20だ。"
"ヒトカゲがあらわれた。 ヒトカゲのHPは18だ。"
"ピカチュウの攻撃! 10万ボルト!ヒトカゲは10ダメージをもらった。 ヒトカゲのHPは8だ。"
"ヒトカゲの攻撃!ひのこ! ピカチュウは5のダメージ。 ピカチュウのHPは15だ。"
"ピカチュウの攻撃! 10万ボルト!ヒトカゲは10ダメージをもらった。 ヒトカゲのHPは0だ。"
"ヒトカゲはたおれた。 ピカチュウのかち。"

では実際にこのコードをoopなしに出力する方法(コーディング)を考える!

今回、動画ではpythonで記述しているが、Rubyのコードに書き換えをしてコーディングにトライしてみる!
no_oop_pokemon.rb
def main
  pikachu = 'ピカチュウ'
  hitokage= 'ヒトカゲ'
  hp_pikachu = 20
  hp_hitokage = 18
  p "#{pikachu}があらわれた。 #{pikachu}のHPは#{hp_pikachu}だ。"
  p "#{hitokage}があらわれた。 #{hitokage}のHPは#{hp_hitokage}だ。"


  while true do
    hp_hitokage = attack_pikachu(hitokage, hp_hitokage)
    if check_fainted(hp_hitokage)
      p "#{hitokage}はたおれた。 #{pikachu}のかち。"
      break
    end

    hp_pikachu = attack_hitokage(pikachu, hp_pikachu)
    if check_fainted(hp_pikachu)
      p "#{pikachu}はたおれた。 #{hitokage}のかち。"
      break
    end
  end
end
  def attack_pikachu(pokemon, hp)
    if hp - 10 > 0
      hp = hp - 10
    else
      hp = 0
    end
    p "ピカチュウの攻撃! 10万ボルト!#{pokemon}は10ダメージをもらった。 #{pokemon}のHPは#{hp}だ。"
    return hp
  end

  def attack_hitokage(pokemon, hp)
    if hp - 5 > 0
      hp = hp - 5
    else
      hp = 0
    end
    p "ヒトカゲの攻撃!ひのこ! #{pokemon}は5のダメージ。 #{pokemon}のHPは#{hp}だ。"
    return hp
  end

  def check_fainted(hp)
    if hp <= 0
      return true
    else
      return false
    end
  end

  main()

上記に以下のように、追加の変数を加えていくと管理などが大変になる。

# 追加変数
speed_pikachu = 11
speed_hitokage = 11

また、ポケモンの種類も増える可能性もある。
このことで、バグにつながる可能性も高くなる。

ここで登場するのが 【オブジェクト指向】。

オブジェクト指向を使うことで、より細かく担当を細分化し、実装しやすくなる。
これ以降に細分化したコードを記載する。

pokemon.rb
class Pokemon
  attr_reader :name, :atk
  attr_accessor :hp

  def initialize(name,hp,atk)
    @name = name
    @hp = hp
    @atk = atk
  end

  def attack(target)
   target.hp -= @atk
    p "#{@name} の攻撃!"
    attack_message(target )
  end

  def  attack_message(target)
   pass
  end
  
  def is_fainted
   return @hp <= 0
  end


  protected
  def name
    @name
  end

  def hp=(value)
   @hp=value
  end

  def atk
   @atk
  end

end

# 子クラスへの継承
class Pikachu < Pokemon
  def initialize
   super('ピカチュウ',20, 10)
  end

  def attack_message(target)
   p "10万ボルト!#{target.send(:name)}#{send(:atk)}ダメージをもらった!#{target.send(:name)}のHPは#{target.send(:hp)}だ。"
  end
end

class Hitokage < Pokemon
  def initialize
   super('ヒトカゲ',18, 5)
  end

  def attack_message(target)
   p "ひのこ!!#{target.send(:name)}#{send(:atk)}ダメージをもらった!#{target.send(:name)}のHPは#{target.send(:hp)}だ。"
  end
end
game.rb
class Game

  def initialize (pokemon1, pokemon2)
    @pokemon1 = pokemon1
    @pokemon2 = pokemon2
  end

  def battle
    start
    # 勝者と敗者のポケモンを返す
    winner, loser = attack
    show_result(winner, loser)
  end

  private

  def start
    p "#{@pokemon1.send(:name)}があらわれた。#{@pokemon1.send(:name)}のHPは#{@pokemon1.send(:hp)}だ。"
    p "#{@pokemon2.send(:name)}があらわれた。#{@pokemon2.send(:name)}のHPは#{@pokemon2.send(:hp)}だ。"
  end

  def attack
    while true do
      @pokemon1.attack(@pokemon2)
        if @pokemon2.is_fainted
          return [@pokemon1, @pokemon2]
        end
      @pokemon2.attack(@pokemon1)
        if @pokemon1.is_fainted
          return [@pokemon2, @pokemon1 ]
        end
    end
  end

  def show_result(winner, loser)
     p "#{loser.send(:name)}はたおれた。#{winner.send(:name)}のかち。"
  end
end
oop_pokemon.rb
# 別ファイルからの読みだし
require_relative "game.rb"
require_relative "pokemon.rb"

 pikachu = Pikachu.new
 hitokage = Hitokage.new
 game  = Game.new(pikachu, hitokage)

 game.battle

Discussion