日常生活でオブジェクト指向が使われている！？

## なぜ知りたいと思ったか？
オブジェクト指向を学習する時に、乗り物やRPGの登場人物に例えるのが多いが、「乗り物やRPGに詳しくない」側にとっては理解しづらい。
オブジェクト指向について調べてみたら、「日常生活でも使われている」とあったので、調べてみようと思った。


## 「普段はオブジェクト指向で物事を考えている」という意味とは？
オブジェクト指向を英語に訳すと「object oriented programming(OOP)」となり、「モノ中心」にソフトウェアを開発するんですね。オブジェクト指向の学習時に、「クラス」と「インスタンス」という用語が出たと思います。

クラス：種類・役割・設計図
インスタンス：具体的なモノ・設計図から作られた実物体


例えば、ホテルサイトでホテルを予約する場合、
①宿泊日付と人数を入力する
②宿泊したい部屋のタイプを選ぶ
③予約内容を確定する
④(システム側で)ユーザーが予約した宿泊情報を登録する
⑤(システム側で)予約完了メッセージを送信する

という一連の行動をすると思います。これを「クラス」と「インスタンス」分類すると、

クラス = 宿泊情報
・予約者や宿泊日付などの情報を持つ

インスタンス = ユーザー(クラス)に情報を渡して実体化させる
・入力情報を渡して、宿泊情報のデータとして作成する

クラスの性質や利用目的に合った情報を渡すと(インスタンス化)、「モノ」としての機能が使えるという事ですね。


## オブジェクト指向を使わないとどうなるか？
オブジェクト指向を使わないと、全ての処理を手順化しないといけなくなります。直線的に上から下に向けて処理する手順化プログラムだと、読み辛いのが分かると思います。

```sample.rb
staying_rooms = [
                  {name: 'スタンダードダブル', max_count: 2, width: '20㎡', room_count: 42},
                  {name: 'ツーペリアツイン', max_count: 2, width: '23㎡', room_count: 38},
                  {name: 'デラックスツイン', max_count: 3, width: '30㎡', room_count: 30},
                  {name: 'レジデンシャルファミリー', max_count: 4, width: '40㎡', room_count: 22}
                ]

puts '名前を入力して下さい'
reserve_name = gets.chomp
puts '宿泊日付を入力して下さい'
staying_date = gets.chomp
puts '宿泊人数を入力して下さい'
staying_count = gets.chomp.to_i
staying_rooms.each_with_index do |staying_room, index|
  puts "#{index} #{staying_room[:name]} 最大定員：#{staying_room[:max_count]} 広さ：#{staying_room[:width]} 残り：#{staying_room[:room_count]}"
end
puts '宿泊する部屋のタイプを番号で入力して下さい'
room_number = gets.chomp.to_i
room_type = staying_rooms[room_number][:name]

puts ''

# 宿泊予約完了メッセージ
puts <<~EOS
  ---------------------------------------------
  #{reserve_name}様、宿泊予約が完了したので、ご確認をお願いします。
  
  宿泊日付：#{staying_date}
  宿泊人数：#{staying_count}名
  宿泊する部屋のタイプ：#{room_type}
  ---------------------------------------------
EOS
```

[実行結果]
```
名前を入力して下さい
上杉
宿泊日付を入力して下さい
2023-12-24
宿泊人数を入力して下さい
2
0 スタンダードダブル 最大定員：2 広さ：20㎡ 残り：42
1 ツーペリアツイン 最大定員：2 広さ：23㎡ 残り：38
2 デラックスツイン 最大定員：3 広さ：30㎡ 残り：30
3 レジデンシャルファミリー 最大定員：4 広さ：40㎡ 残り：22
宿泊する部屋のタイプを番号で入力して下さい
1

---------------------------------------------
上杉様、宿泊予約が完了したので、ご確認をお願いします。

宿泊日付：2023-12-24
宿泊人数：2名
宿泊する部屋のタイプ：ツーペリアツイン
---------------------------------------------
```

それをオブジェクト指向にするとどうでしょうか？

```staying.rb
class Staying
  attr_accessor :reserve_name, :staying_date, :staying_count, :room_type
  
  # 予約情報を設定
  def initialize(reserve_name, staying_date, staying_count, room_type)
    @reserve_name = reserve_name
    @staying_date = staying_date
    @staying_count = staying_count
    @room_type = room_type
  end
end
```

```hotel.rb
class Hotel
  attr_accessor :staying_rooms
  
  @@staying_rooms = [
                      {name: 'スタンダードダブル', max_count: 2, width: '20㎡', room_count: 42},
                      {name: 'ツーペリアツイン', max_count: 2, width: '23㎡', room_count: 38},
                      {name: 'デラックスツイン', max_count: 3, width: '30㎡', room_count: 30},
                      {name: 'レジデンシャルファミリー', max_count: 4, width: '40㎡', room_count: 22}
                    ]
  
  # 部屋情報を出力
  def self.rooms_info
    @@staying_rooms.each_with_index do |staying_room, index|
      puts "#{index} #{staying_room[:name]} 最大定員：#{staying_room[:max_count]} 広さ：#{staying_room[:width]} 残り：#{staying_room[:room_count]}"
    end
  end
  
  # 部屋情報を取得
  def self.staying_rooms
    @@staying_rooms
  end
end
```

```main.rb
require './staying'
require './hotel'

class Main
  puts '名前を入力して下さい'
  reserve_name = gets.chomp
  puts '宿泊日付を入力して下さい'
  staying_date = gets.chomp
  puts '宿泊人数を入力して下さい'
  staying_count = gets.chomp.to_i
  
  # ホテル情報
  Hotel.rooms_info
  puts '宿泊する部屋のタイプを番号で入力して下さい'
  type_number = gets.chomp.to_i
  
  # 宿泊情報
  stay_info = Staying.new(reserve_name, staying_date, staying_count, Hotel.staying_rooms[type_number][:name])
  # 宿泊予約完了メッセージ
  puts <<~EOS
    ---------------------------------------------
    #{stay_info.reserve_name}様、宿泊予約が完了したので、ご確認をお願いします。
    
    宿泊日付：#{stay_info.staying_date}
    宿泊人数：#{stay_info.staying_count}名
    宿泊する部屋のタイプ：#{stay_info.room_type}
    ---------------------------------------------
  EOS
end
```

手順化プログラムと比べて、クラス毎の役割が明確になり、一元管理しやすくなった点に気付きましたか？
宿泊情報クラスに予約者や宿泊日付などのプロパティがあり、インスタンス化すれば宿泊情報のデータとして活用できるんですね。


・まとめ
洗濯機：必要な洗剤の量を検出する・選択したコースに応じて洗濯から脱水を行う・洗濯が終わった時に音を鳴らす
という様に、対象物(対象者)には色んな役割があることを、日常生活を過ごして気付かなかった。オブジェクト指向を「モノ」として考えても定着しないから、「対象物(対象者)にどんな役割があるか」に着目すると、オブジェクト指向プログラミングを設計しやすくなると感じた。