Ruby | 2週間で身につく、アプリを作りながら学ぶRubyの基本 - 5日目

Ruby Ruby
スポンサーリンク
スポンサーリンク

5日目のゴールとテーマ

5日目のテーマは「ハッシュから一歩進んで、“自分の型(クラス)”を作る」です。
4日目までは、1人分の情報をハッシュで表現していました。

今日はそこから一歩進めて、

「人」を表す Person クラスを作る
person.name や person.age のように扱えるようにする
自己紹介文を作るメソッドを Person の中に持たせる

という、「オブジェクト指向」の入り口に入っていきます。


クラスとオブジェクトをイメージでつかむ

設計図(クラス)と実物(オブジェクト)

クラスは「設計図」、オブジェクトは「その設計図から作られた実物」と考えると分かりやすいです。

Person というクラスは、「人ってこういう情報を持っているよね」という設計図です。
例えば、名前・年齢・趣味・年齢コメントなど。

そこから実際に作られた1人分のデータが、Person オブジェクトです。

「たろうさん」という人を表す Person
「はなこさん」という人を表す Person

という感じで、同じ設計図から何人分でも作れます。


Personクラスを定義してみる

最小限のPersonクラス

まずは、名前・年齢・趣味だけを持つシンプルな Person クラスを書いてみます。

class Person
  attr_accessor :name, :age, :hobby

  def initialize(name, age, hobby)
    @name = name
    @age = age
    @hobby = hobby
  end
end
Ruby

ここで出てきた新しい要素を、丁寧に分解します。

attr_accessorとは何か

attr_accessor :name, :age, :hobby は、

name, age, hobby という「属性(プロパティ)」を
外から読み書きできるようにするための“おまじない”

です。

これを書いておくと、

person = Person.new("たろう", 25, "ゲーム")
puts person.name      # 読める
person.hobby = "読書" # 書ける
Ruby

のように、ドットでアクセスできます。

initializeと@変数

def initialize(name, age, hobby) は「コンストラクタ」と呼ばれる特別なメソッドです。
Person.new(...) したときに、自動的に呼ばれます。

@name や @age のような @ から始まる変数は「インスタンス変数」と呼ばれます。
そのオブジェクト専用の“中身”を表します。

@name = name は、

引数で受け取った name を、この人(オブジェクト)の @name に保存する

という意味です。


Personオブジェクトを作って使ってみる

newで「1人分の人」を作る

さっそく Person を使ってみます。

person1 = Person.new("たろう", 25, "ゲーム")
person2 = Person.new("はなこ", 19, "カフェ巡り")

puts person1.name
puts person1.age
puts person1.hobby

puts person2.name
puts person2.age
puts person2.hobby
Ruby

実行すると、それぞれの人の情報が表示されます。

ここで感じてほしいのは、

「ハッシュのキーでアクセスしていたものが、ドットでアクセスできるようになった」

ということです。

person[:name] ではなく person.name
person[:age] ではなく person.age

のように書けると、「人」という概念がコードの中でより自然に扱えます。


Personに「年齢コメントを返すメソッド」を持たせる

ロジックをクラスの中に閉じ込める

4日目では、年齢コメントを決めるメソッドを別に書いていました。
これを Person の中に入れてしまいましょう。

class Person
  attr_accessor :name, :age, :hobby

  def initialize(name, age, hobby)
    @name = name
    @age = age
    @hobby = hobby
  end

  def age_comment
    if @age <= 0
      "年齢はひみつなんですね。"
    elsif @age < 20
      "とても若いですね!"
    elsif @age < 40
      "働き盛りの世代ですね。"
    else
      "人生経験が豊富そうですね。"
    end
  end
end
Ruby

ここでの重要ポイントは、

年齢コメントのロジックが Person の中に移動した
@age を直接使って判定している
外からは person.age_comment と呼ぶだけでよくなる

ということです。

実際に呼んでみる

person = Person.new("たろう", 25, "ゲーム")

puts person.name
puts person.age
puts person.hobby
puts person.age_comment
Ruby

これで、「この人に対するコメント」を
Person 自身が知っている、という形になります。


Personに「自己紹介文を返すメソッド」を持たせる

自己紹介の責任もPersonに渡す

今度は、自己紹介文を作るメソッドも Person に持たせます。

class Person
  attr_accessor :name, :age, :hobby

  def initialize(name, age, hobby)
    @name = name
    @age = age
    @hobby = hobby
  end

  def age_comment
    if @age <= 0
      "年齢はひみつなんですね。"
    elsif @age < 20
      "とても若いですね!"
    elsif @age < 40
      "働き盛りの世代ですね。"
    else
      "人生経験が豊富そうですね。"
    end
  end

  def introduction
    text = ""
    text += "はじめまして、#{@name}です。\n"
    text += "年齢は#{@age}歳です。#{age_comment}\n"
    text += "好きなことは#{@hobby}です。\n"
    text += "よろしくお願いします!\n"
    text
  end
end
Ruby

ここで深掘りしたいポイントは、

自己紹介文の中で age_comment メソッドを呼んでいる
@name, @age, @hobby を直接使って文章を組み立てている
最後に text を返している(Rubyでは最後の式が戻り値になる)

ということです。

これで、外からはこう書けます。

person = Person.new("たろう", 25, "ゲーム")
puts person.introduction
Ruby

「自己紹介を作る」という責任が、Person クラスの中にきれいに収まりました。


入力からPersonオブジェクトを作る

ユーザー入力を使ってPersonを生成する

今度は、gets を使って Person を作るメソッドを書きます。

def build_person_from_input
  puts "あなたの名前を教えてください:"
  name = gets.chomp

  puts "あなたの年齢を教えてください:"
  age_text = gets.chomp
  age = age_text.to_i

  puts "あなたの好きなこと(趣味)を教えてください:"
  hobby = gets.chomp

  person = Person.new(name, age, hobby)
  person
end
Ruby

ここでの流れは、

名前・年齢・趣味を聞く
年齢は to_i で整数に変換する
Person.new で1人分のオブジェクトを作る
その Person を戻り値として返す

というものです。

これで、入力から直接 Person を作れるようになりました。


Personの配列で「名簿アプリ」にする

複数人分のPersonを配列にためる

4日目では「ハッシュの配列」でしたが、
5日目では「Person の配列」にしてみます。

puts "何人分の情報を登録しますか?"
count_text = gets.chomp
count = count_text.to_i

people = []

i = 1
while i <= count
  puts "========================"
  puts "#{i}人目の情報を入力します。"

  person = build_person_from_input
  people << person

  i += 1
end
Ruby

これで、people には Person オブジェクトが順番に入ります。

全員分の自己紹介を表示する

puts "========================"
puts "全員分の自己紹介を表示します。"

people.each_with_index do |person, idx|
  puts "------------------------"
  puts "#{idx + 1}人目の自己紹介:"
  puts person.introduction
end
Ruby

ここでのポイントは、

配列の中身が「ただの文字列」でも「ハッシュ」でもなく、「Person オブジェクト」になっている
自己紹介文は person.introduction と呼ぶだけでよい
年齢コメントのロジックも Person の中に隠れている

ということです。


クラスを使うメリットを整理する

「データ」と「振る舞い」がひとまとまりになる

ハッシュのときは、

データ(name, age, hobby)はハッシュ
年齢コメントのロジックは別メソッド
自己紹介文を作るロジックも別メソッド

という形でした。

クラスにすると、

Person が「データ(@name, @age, @hobby)」と
「振る舞い(age_comment, introduction)」を両方持つ

という形になります。

「人に関することは Person を見れば分かる」という状態です。

コードの読みやすさが上がる

例えば、こんなコードを見たときに、

people.each do |person|
  puts person.introduction
end
Ruby

「people に入っている“人たち”が、順番に自己紹介しているんだな」
と、ほぼ日本語の感覚で読めます。

クラスをうまく設計すると、
コードが「何をしたいのか」をそのまま表現してくれるようになります。


5日目のまとめ

今日のキーワードを整理します。

class
自分で新しい「型(設計図)」を定義するためのキーワード。
Person クラスは「人」を表す設計図。

initialize
Person.new(...) したときに自動で呼ばれる特別なメソッド。
引数を受け取り、インスタンス変数(@name など)にセットする。

インスタンス変数(@name など)
そのオブジェクト専用の“中身”。
クラスの中のどのメソッドからもアクセスできる。

attr_accessor
person.name や person.name = "..." のように、
外から読み書きできる属性を定義するためのショートカット。

メソッドをクラスに持たせる
age_comment や introduction のように、
そのクラスに関係する処理をクラスの中に閉じ込めることで、
「そのクラスを見れば、その概念に関することが分かる」状態になる。

タイトルとURLをコピーしました