更新日:
【Ruby】 たい焼きで理解するオブジェクト指向におけるクラスの概念
クラスとは、インスタンスを作成する時の「元となる設計図のこと」です。
用語 | 役割 | 例1 | 例2 |
---|---|---|---|
クラス | 設計図 | 車の設計図 | たい焼きの型 |
インスタンス | 設計図を元に作成される実物体 | 黒い車、赤い車 | クリームのたい焼き あんこのたい焼き |
Rubyは、「もの」を組み立てる様に表現してコンピュータに指示するオブジェクト指向プログラミング言語です。「もの」を組み立てる際の設計図を「クラス」と呼び、その「設計図から作成された実物体」のことを「インスタンス」と呼びます。
クラスとインスタンスの事前知識
この章では、クラスとインスタンスの事前知識について解説します。
オブジェクト指向プログラミング言語とは
プログラミングとは、コンピュータが理解できる言葉を並べてプログラムを作ることです。その際に、プログラマの意図した順番通りにコンピュータを動作させる指示を出しているのです。
プログラムを意図した順番通りに表現する代表的な方法が下記の3つです。
プログラムの表現方法 | プログラムの流れ | |
---|---|---|
1 | オブジェクト指向プログラミング | 「もの」を組み立てる様に表現して コンピュータに指示する |
2 | 手続き型プログラミング | プログラムを上から順番に処理を実行する |
3 | 関数型プログラミング | 関数の組み合わせによって プログラムを組み立てる様に表現する |
このプログラムの表現方法の中で「Rubyは、オブジェクト指向プログラミング言語」です。
物を組み立ててコンピュータを動作させる為に、物の設計図であるクラスと物の実物体であるオブジェクトが必要なのです。
「クラス」と「インスタンス」をイメージしてみよう
クラスとインスタンスは、次のように設計図と設計図から作成される実物体と言われています。
より具体的なイメージをクラスとインスタンスで表現すると、次のように「たい焼き」に例えられる事が多いです。
たい焼きは、たい焼きの型で様々な種類の味を持つたい焼きを作ることができますね。このイメージを実際にコードにしてクラスとインスタンスの理解を深めていきます。
メソッドの特徴を理解しよう
メソッドの特徴を理解することが出来ると、このあとのクラス内で定義するメソッドやインスタンス変数との違いが比較しやすくなります。
メソッドの基本的な書き方は、次のコードのようになります。
1
2
3
4
5
6
def メソッド名
# 処理
end
# メソッド実行
メソッド名
1
2
3
4
5
6
7
def say_hello
puts "hello!"
end
# say_helloメソッド実行
say_hello
#=> hello!
メソッドは以下の特徴があります。
- メソッドに値を渡す事が出来る
- メソッド内で最後に評価された値を返す
- メソッド内で定義した変数は、外部からアクセスすることが出来ない
コードを見ながら確認していきましょう。
1
2
3
4
5
6
7
8
# 引数を追加
def say_hello(name)
puts "#{name}, hello!"
end
# say_helloメソッド実行
say_hello("mari")
#=> mari, hello!
1
2
3
4
5
6
7
def say_hello(name)
puts "#{name}, hello!" #ここがメソッド内で最後に評価されている
end
# say_helloメソッド実行
say_hello("mari")
#=> mari, hello!
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メソッドを利用して「@がついたインスタンス変数」に代入します。
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」を代入した為、この情報を保持しています。
インスタンスメソッドは、このインスタンスごとに保持している情報を使って処理を書くことが出来ます。
実際にコードで見ていきましょう。
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円です。
作成したインスタンスからインスタンスメソッドを実行することで、インスタンス毎に違う結果を得ることが出来るのです。
クラスメソッドの定義
先ほどのインスタンスメソッドは、インスタンスから呼び出すことが出来ましたが、その他にもクラスから呼び出すことが出来るクラスメソッドがあります。
クラスメソッドとは、インスタンスに依存せずにクラス本体に紐づけられるメソッドのことです。
インスタンスの持つデータを使う必要のない処理は、クラスメソッドで定義します。
クラスメソッドは、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冊です!
オブジェクト指向設計の名著として名高い“Practical Object-Oriented Design in Ruby”,待望の翻訳版!
用語の整理
ここまでたくさんの用語が出てきましたが、1つ1つ整理して理解を深めていきましょう。
用語 | 意味 |
---|---|
プログラミング | コンピュータが理解できる言葉を並べて プログラムを作る |
オブジェクト指向プログラミング | 「もの」を組み立てる様に表現してコンピュータに指示する |
オブジェクト | Rubyで扱うことが出来る全てのデータ 何らかのクラスに属しているので、インスタンスとも呼ぶ |
インスタンス | クラスから作成された実物体 |
クラス | オブジェクト指向における設計図 |
initailzeメソッド | インスタンス作成時に実行されるメソッド |
インスタンス変数(@test) | インスタンスごとに値を保持することが出来る |
クラス変数(@@test) | 全てのインスタンスで共有される変数 |
インスタンスメソッド | 作成したインスタンスから実行出来るメソッド インスタンスの保持するデータを使うことが出来る |
クラスメソッド | インスタンスに依存せずに クラス本体に紐づけられるメソッド |
この記事のまとめ
- クラスとは、インスタンスを作成する時の元となる設計図のこと
- Rubyは、「もの」を組み立てる様に表現してコンピュータに指示するオブジェクト指向プログラミング言語!
- ものを組み立てる時は、設計図であるクラスと実物体であるインスタンスを使用する