すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Ruby

【Ruby】 たい焼きで理解するオブジェクト指向におけるクラスの概念

ぴっかちゃん
ぴっかちゃん

クラスとは、インスタンスを作成する時の「元となる設計図のこと」です。

概念の画像

用語 役割 例1 例2
クラス 設計図 車の設計図 たい焼きの型
インスタンス 設計図を元に作成される実物体 黒い車、赤い車 クリームのたい焼き
あんこのたい焼き

Rubyは、「もの」を組み立てる様に表現してコンピュータに指示するオブジェクト指向プログラミング言語です。「もの」を組み立てる際の設計図を「クラス」と呼び、その「設計図から作成された実物体」のことを「インスタンス」と呼びます。

クラスとインスタンスの事前知識

この章では、クラスとインスタンスの事前知識について解説します。

オブジェクト指向プログラミング言語とは

プログラミングとは、コンピュータが理解できる言葉を並べてプログラムを作ることです。その際に、プログラマの意図した順番通りにコンピュータを動作させる指示を出しているのです。

プログラムを意図した順番通りに表現する代表的な方法が下記の3つです。

プログラムの表現方法 プログラムの流れ
1 オブジェクト指向プログラミング 「もの」を組み立てる様に表現して
コンピュータに指示する
2 手続き型プログラミング プログラムを上から順番に処理を実行する
3 関数型プログラミング 関数の組み合わせによって
プログラムを組み立てる様に表現する

このプログラムの表現方法の中で「Rubyは、オブジェクト指向プログラミング言語」です。

オブジェクト指向プログラミング

物を組み立ててコンピュータを動作させる為に、物の設計図であるクラスと物の実物体であるオブジェクトが必要なのです。

ポイント
  1. Rubyはオブジェクト指向プログラミング言語
  2. オブジェクト指向とは、ものを組み立てる様にしてコンピュータに指示するプログラムの表現方法
  3. ものを組み立ててプログラムを表現するために、物の設計図であるクラスと設計図から作成される実物体のインスタンスが必要になる

「クラス」と「インスタンス」をイメージしてみよう

クラスとインスタンスは、次のように設計図と設計図から作成される実物体と言われています。

クラスとインスタンスのイメージ

より具体的なイメージをクラスとインスタンスで表現すると、次のように「たい焼き」に例えられる事が多いです。

たい焼きと型

たい焼きは、たい焼きの型で様々な種類の味を持つたい焼きを作ることができますね。このイメージを実際にコードにしてクラスとインスタンスの理解を深めていきます。

メソッドの特徴を理解しよう

メソッドの特徴を理解することが出来ると、このあとのクラス内で定義するメソッドやインスタンス変数との違いが比較しやすくなります。

メソッドの基本的な書き方は、次のコードのようになります。

メソッドの基本的な書き方
1
2
3
4
5
6
def メソッド名
  # 処理
end

# メソッド実行
メソッド名
say_helloメソッドを定義して実行する
1
2
3
4
5
6
7
def say_hello
  puts "hello!"
end

# say_helloメソッド実行
say_hello
#=> hello!

メソッドは以下の特徴があります。

  1. メソッドに値を渡す事が出来る
  2. メソッド内で最後に評価された値を返す
  3. メソッド内で定義した変数は、外部からアクセスすることが出来ない

コードを見ながら確認していきましょう。

1. メソッドに値を渡すことが出来る
1
2
3
4
5
6
7
8
# 引数を追加
def say_hello(name)
  puts "#{name}, hello!"
end

# say_helloメソッド実行
say_hello("mari")
#=> mari, hello!
2. メソッド内で最後に評価された値を返す
1
2
3
4
5
6
7
def say_hello(name)
  puts "#{name}, hello!" #ここがメソッド内で最後に評価されている
end

# say_helloメソッド実行
say_hello("mari")
#=> mari, hello!
3. メソッド内で定義した変数は外部からアクセスすることが出来ない
1
2
3
4
5
6
7
8
9
# メソッド内に変数を追加
def say_hello
  other_name = "taro"
  puts "hello!"
end

# メソッド内の変数other_nameをメソッド外から指定するとエラーが出る
puts other_name
#=> NameError: undefined local variable or method `other_name' for main:Object

メソッドについて詳しくは、「メソッドを徹底解説!」を参考にしてください。

クラスの作り方

クラスから少し離れてしまいしたが、先ほどの「たい焼きのイメージ」と「メソッドの特徴」を踏まえた上でクラスを作成して作っていきましょう。

たい焼きと型

クラスの定義

クラスの定義は、以下のように記述します。

クラスの定義
1
2
3
class クラス名
  # メソッドなど
end

ここで重要なのは、メソッドの時と違いクラス名の最初の文字が大文字ということです。

クラス名の最初の文字は、必ず大文字にする
1
2
3
4
5
6
class Taiyaki

  def メソッド
  end

end

インスタンス作成

インスタンスは、以下のようにクラスから作成します。

インスタンスを作成する
1
クラス名.new

たい焼きの型からたい焼きを作り出すには、以下のように記述します。

たい焼きの設計図を作成
1
2
3
4
5
6
7
8
9
10
class Taiyaki

  def メソッド
  end

end

# たい焼きの設計図からたい焼きを作成
taiyaki = Taiyaki.new
# => #<Taiyaki:0x007fd948934e90>

Taiyaki.newの返り値が<Taiyaki:0x007fd948934e90>なので、たい焼きのインスタンス(オブジェクト)が作成された事が分かります。

initailzeメソッドとインスタンス変数

たい焼きを作る事が出来ましたが、このままではたい焼きの味(taste)や値段(price)が分かりません。

たい焼きに情報を持たせる為にインスタンス作成時に、たい焼きの情報を引数に渡します。

様々な種類のたい焼き

引数で渡された値は、インスタンス作成時に実行されるinitializeメソッドを利用して「@がついたインスタンス変数」に代入します。

initializeメソッドの引数にたい焼きの情報を渡す
1
2
3
4
5
6
7
8
9
10
11
12
class Taiyaki
  # インスタンス作成の時に実行される
  def initialize(taste, price)
    # インスタンス変数には@をつける
    @taste = taste
    @price = price
  end
end

# newした際にinitializeメソッドが実行され、引数の値がインスタンス変数に代入される
anko_taiyaki = Taiyaki.new("あんこ", 250)
#=> <Taiyaki:0x007fd9489cdb18 @taste="あんこ", @price=250>

インスタンスを作成するときに、initializeメソッド内でインスタンス変数に引数で渡した値を代入させることによって、インスタンス変数は、インスタンスごとに値を保持することが出来ます。

たい焼きを作るときに、それぞれのたい焼き毎に味や値段を変える事が出来るのです。

インスタンス変数をたい焼きで例える

メソッドの特徴として、メソッドの内で定義した変数はメソッドの外では利用できませんでしたが、インスタンス変数はインスタンス内であればどこでも呼び出すことが出来ます。

この特徴は次のインスタンスメソッドを使うとより理解する事が出来ます。

ポイント
  1. initializeメソッドとは、インスタンス作成時に実行されるメソッドのこと
  2. インスタンス変数は、インスタンスごとに値を保持することが出来る

インスタンスメソッド

インスタンスメソッドとは、作成したインスタンスから実行出来るメソッドのことです。

先ほど作成したanko_taiyakiのインスタンスは、initializeメソッドでインスタンス変数に「@taste = あんこ, @price = 250」を代入した為、この情報を保持しています。

インスタンスメソッドは、このインスタンスごとに保持している情報を使って処理を書くことが出来ます。

インスタンスメソッドの流れ

実際にコードで見ていきましょう。

インスタンスメソッドの使用例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# たい焼きの設計図を作成
class Taiyaki

  # インスタンス作成の時に実行される
  def initialize(taste, price)
    @taste = taste
    @price = price
  end

  # 作成したインスタンスから実行出来るインスタンスメソッド
  # インスタンスによって、@tasteと@priceの値が異なる
  def show_info
      puts "#{@taste}味のたい焼きは#{@price}円です。"
  end
end

# anko_taiyakiのインスタンスを作成
anko_taiyaki = Taiyaki.new("あんこ", 250)
#=> <Taiyaki:0x007fd9489cdb18 @taste="あんこ", @price=250>


# 作成したanko_taiyakiのインスタンスからshow_infoインスタンスメソッドを実行する
anko_taiyaki.show_info
# => あんこ味のたい焼きは250円です。

show_infoインスタンスメソッドは、作成したインスタンスによって、文章の内容が異なります。
これは、インスタンスごとに保持するデータを変えることが出来るからです。

試しにカスタード味のたい焼きを作って確認しましょう。

インスタンスを変更してインスタンスメソッドを実行

カスタード味のたい焼きを作成する
1
2
3
4
5
6
custard_taiyaki = Taiyaki.new("カスタード", 300)
=> #<Taiyaki:0x007fd9489b6f58 @taste ="カスタード", @price=300>

# カスタード味と値段の値を保持したインスタンスを使ってインスタンスメソッドを呼び出す
custard_taiyaki.show_info
# => カスタード味のたい焼きは300円です。

作成したインスタンスからインスタンスメソッドを実行することで、インスタンス毎に違う結果を得ることが出来るのです。

ポイント
  1. インスタンスメソッドとは、作成したインスタンスから実行出来るメソッドのこと
  2. インスタンスの保持するデータを使うことが出来る

クラスメソッドの定義

先ほどのインスタンスメソッドは、インスタンスから呼び出すことが出来ましたが、その他にもクラスから呼び出すことが出来るクラスメソッドがあります。

クラスメソッドとは、インスタンスに依存せずにクラス本体に紐づけられるメソッドのことです。
インスタンスの持つデータを使う必要のない処理は、クラスメソッドで定義します。

クラスメソッドは、2つの定義方法があります。

クラスメソッドの定義方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# クラスメソッドの定義方法1
class クラス名
  def self.クラスメソッド名
  end
end

# クラスメソッドの定義方法2
class クラス名  
  # この中で定義するとクラスメソッドと認識される
  class << self
    # メソッド名にselfは必要ない
    def test
    end
  end
end

クラスメソッドは、以下のように呼び出すことが出来ます。

クラスメソッドの呼び出し
1
クラス名.クラスメソッド名

クラスメソッドの使用例は、次のクラス変数と合わせて解説します。

クラス変数

インスタンス変数の他に、クラス変数という@が2つ付く変数があります。
インスタンス変数が作成された各インスタンスごとに共有される変数だったのに対して、クラス変数は、全てのインスタンスで共有される変数です。

クラス変数の説明

たい焼きが全部で何個作成されたか分かるクラス変数「@@total_taiyaki_count」と、それを案内するクラスメソッドを定義して見ましょう。

クラスメソッドとクラス変数を追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# たい焼きの設計図を作成
class Taiyaki

  # 全てのインスタンスで共有されるクラス変数
   @@total_taiyaki_count = 0

  # インスタンス作成の時に実行される
  def initialize(taste, price)
    @taste = taste
    @price = price

    # インスタンスが作成(new)される毎にカウントアップ
    @@total_taiyaki_count += 1
  end

  # インスタンスメソッド
  def show_info
      puts "#{@taste}味のたい焼きは#{@price}円です。"
  end

  # クラスメソッド
   def self.show_all_count
     puts "たい焼きは全部で#{@@total_taiyaki_count}個作成されました。"
   end

end

クラス変数「@@total_taiyaki_count」によってTaiyakiクラスからインスタンスを作成する度に1ずつ増える為、たい焼きの作成した個数を知ることが出来ます。

インスタンス作成してクラスメソッドを実行する
1
2
3
4
5
6
7
8
9
10
11
# anko_taiyakiのインスタンスを作成(カウントアップされる)
anko_taiyaki = Taiyaki.new("あんこ", 250)
# => <Taiyaki:0x007fd9489cdb18 @taste="あんこ", @price=250>

# カスタード味のたい焼きを作成する(カウントアップされる)
custard_taiyaki = Taiyaki.new("カスタード", 300)
# => <Taiyaki:0x007fd9489b6f58 @taste ="カスタード", @price=300>

# たい焼きの個数を調べるためにshow_all_countクラスメソッドを実行する
Taiyaki.show_all_count
#=> たい焼きは全部で2個作成されました。

手元に置いて何度も読み返したい1冊!

こちらの「オブジェクト指向設計実践ガイド」は、オブジェクト指向言語におけるクラス設計の基本をRubyで学ぶことができる良書です。

オブジェクト指向についての解説だけではなく、その実践方法まで書いてあります。

「どのようにオブジェクト指向でRubyのプログラムを書けばよいのか」を知ることができます。また、ダックタイピングや効率的なテストの書き方など実務に役立つ内容が満載です。

初学者にはやや難しい内容になっていますが、最初から全て理解しようとするのではなく手元に置いて必要になったら都度見返すのが良いでしょう。

Rubyを扱うなら必ず読んでおきたい1冊です!

オブジェクト指向設計実践ガイド本
オブジェクト指向設計実践ガイド ~Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方

オブジェクト指向設計の名著として名高い“Practical Object-Oriented Design in Ruby”,待望の翻訳版!

用語の整理

ここまでたくさんの用語が出てきましたが、1つ1つ整理して理解を深めていきましょう。

用語 意味
プログラミング コンピュータが理解できる言葉を並べて
プログラムを作る
オブジェクト指向プログラミング 「もの」を組み立てる様に表現してコンピュータに指示する
オブジェクト Rubyで扱うことが出来る全てのデータ
何らかのクラスに属しているので、インスタンスとも呼ぶ
インスタンス クラスから作成された実物体
クラス オブジェクト指向における設計図
initailzeメソッド インスタンス作成時に実行されるメソッド
インスタンス変数(@test) インスタンスごとに値を保持することが出来る
クラス変数(@@test) 全てのインスタンスで共有される変数
インスタンスメソッド 作成したインスタンスから実行出来るメソッド
インスタンスの保持するデータを使うことが出来る
クラスメソッド インスタンスに依存せずに
クラス本体に紐づけられるメソッド

この記事のまとめ

  • クラスとは、インスタンスを作成する時の元となる設計図のこと
  • Rubyは、「もの」を組み立てる様に表現してコンピュータに指示するオブジェクト指向プログラミング言語!
  • ものを組み立てる時は、設計図であるクラスと実物体であるインスタンスを使用する