【Ruby】オブジェクト指向で設計するクラスとインスタンスをピカ1分かりやすく解説!

Ruby

クラスとは?

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

概念の画像

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

クラスの概念を理解する為に「オブジェクト指向」を理解することが必要です。まずは、オブジェクト指向について解説していきます。

オブジェクト指向プログラミング言語
リンクをコピーしました

プログラミングとは、コンピュータが理解できる言葉を並べてプログラムを作ることです。

その際に、プログラマの意図した順番通りにコンピュータを動作させる指示を出しているのです。

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

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

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

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

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

ピカわかマークポイント

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

「クラス」と「インスタンス」をイメージしてみよう
リンクをコピーしました

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

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

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

たい焼きと型

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

メソッドの特徴を理解しよう
リンクをコピーしました

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

メソッドの基本的な書き方は下記になります。

ruby
1
2
3
4
5
6
7
def メソッド名
  # 処理
end

# メソッド実行
メソッド名

ruby
1
2
3
4
5
6
7
8
# say_helloメソッドを定義
def say_hello
  puts "hello!"
end

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

メソッドの特徴
リンクをコピーしました

メソッドは下記の特徴があります。コードを見ながら確認していきましょう。

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

# 引数を追加
def say_hello(name)
  puts "#{name}, hello!"
end

# say_helloメソッド実行
say_hello("mari")
#=> mari, hello!
2. メソッド内で最後に評価された値を返す
1
2
3
4
5
6
7
8
9

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
10
11

# メソッド内に変数を追加
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

クラスの作り方
リンクをコピーしました

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

たい焼きと型

クラスは下記の様に定義します。

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

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

ruby
1
2
3
4
5
6
7
8
# クラス名の最初の文字は必ず大文字にすること
class Taiyaki

  def メソッド
  end

end

インスタンス作成
リンクをコピーしました

インスタンスは下記の様にクラスから作成します。

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

通常はインスタンス作成の際に、変数に入れてインスタンスを活用していきます。

たい焼きの型からたい焼きを作り出すと、下記のコードになります。

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

  def メソッド
  end

end

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

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

initailzeメソッドとインスタンス変数
リンクをコピーしました

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

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

様々な種類のたい焼き

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

ruby
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メソッド内でインスタンス変数に引数で渡した値を代入させることによって、インスタンス変数は、インスタンスごとに値を保持することが出来ます。

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

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

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

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

インスタンスメソッド
リンクをコピーしました

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

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

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

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

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

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

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

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

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

# カスタード味と値段の値を保持したインスタンスを使ってインスタンスメソッドを呼び出す

custard_taiyaki.show_info
# => カスタード味のたい焼きは300円です。

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

クラスメソッドの定義
リンクをコピーしました

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

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

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

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

# クラスメソッドの定義方法2
class クラス名

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

end

クラスメソッドは下記の様に呼び出すことが出来ます。

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

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

クラス変数
リンクをコピーしました

インスタンス変数の他に、クラス変数という@が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
28
29
# たい焼きの設計図を作成
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

  # クラスメソッド
   class << self
     def show_all_count
       puts "たい焼きは全部で#{@@total_taiyaki_count}個作成されました。"
     end
   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つ1つ整理して理解を深めていきましょう。

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

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