※ カリキュラムでは、Cloud9のターミナルやエディタを利用します。
まだ用意していない方は「AWS Cloud9を準備しよう」を参考に導入してください。
クラスとインスタンスのイメージを図で掴もう
クラスは、オブジェクトの「設計図」に相当するものです。インスタンスは、設計図であるクラスに基づいて生成されるオブジェクトの実物体のことです。
設計図であるクラスには、データの項目やメソッドを設定します。たとえとしてよく用いられるのは、「たい焼き器」と「たい焼き」です。
1つのたい焼き器(クラス)によって、見た目が同じ形のたい焼き(インスタンス)をどんどん作ることができます。
もちろん材料を入れることで、たい焼き毎に中身の味を変えられます。
たい焼きの見た目が同じ形でも、たい焼き(インスタンス)ごとに「味」や「値段」といった中身が異なる情報を持たせることができます。
この辺りは実際のソースコードをみた方が理解しやすいので、順を追って説明します。
クラスとインスタンスを作ってみよう
それでは、実際にコードをみながらクラスとインスタンスを作ってみましょう。
taiyaki.rb
という名前のファイルを用意しておきましょう。
クラスを定義しよう
新しいクラスを定義するには、キーワードのclass
を使います。
1
2
class クラス名
end
それでは、たい焼きの設計図である「Taiyakiクラス」を定義してみましょう。
以下のソースコードを「taiyaki.rb」に書いてみましょう。
1
2
class Taiyaki
end
クラスには、クラス名の先頭は大文字にするという決まりがあるので、taiyaki
ではなくTaiyaki
と書きます。
インスタンスを生成しよう
インスタンスを生成するには、クラスに対して「newメソッド」を呼び出します。
1
クラス名.new
それでは、たい焼きの設計図であるTaiyakiクラスから「たい焼き」を作ってみましょう。
以下のようにTaiyaki.new
を「taiyaki.rb」に書いてみましょう。
1
2
3
4
class Taiyaki
end
Taiyaki.new
以下のようにTaiyaki.new
によって「Taiyakiクラスのインスタンス」が生成されます。
また、たい焼き器からいくつでもたい焼きを作れるように、クラスからは1つのインスタンスだけではなく、newメソッドを繰り返し呼び出すことで、複数のインスタンスを生成することができます。
initializeメソッド
インスタンス生成したときに実行したい処理があれば、クラスの中に「initializeメソッド」という特殊なメソッドを定義しておきます。initializeメソッドとは、newメソッドでインスタンスを生成した際に自動で呼ばれるメソッドのことです。
initializeメソッドは、以下のようにクラスの中に定義します。
1
2
3
4
5
class クラス名
def initialize
#インスタンス生成時に実行したい処理を書く
end
end
それでは、Taiyakiクラスにinitializeメソッドを定義して、インスタンス生成時に自動で呼び出されることを確認してみましょう。
以下のソースコードをtaiyaki.rbに書き、rubyコマンドで実行してみましょう。
1
2
3
4
5
6
7
class Taiyaki
def initialize
puts "initializeメソッドが実行されました。"
end
end
Taiyaki.new
動画のようにtaiyaki.rbを実行すると、ターミナルにはinitializeメソッドが実行されました
と出力されます。
前回の章では「メソッドを実行するには『メソッド呼び出し』が必要」と学びましたね。
しかし今回はTaiyaki.new
が実行されると、initializeメソッドが自動で呼び出されるので、以下のような動作になります。
初学者の方がよく混乱してしまうのが「newメソッド」と「initializeメソッド」だよ。2つのメソッドの違いをしっかりおさえておこう!
newメソッドは「クラスのインスタンスを生成する」だよ。initializeメソッドは「newメソッドが実行されると自動で呼び出される」だよね!
initializeメソッドで引数を使う場合
initializeメソッドへの引数の指定は、以下のようにnewメソッドの引数で指定します。
1
2
3
4
5
6
7
class クラス名
def initialize(仮引数)
#インスタンス生成時に実行したい処理を書く
end
end
クラス名.new(実引数)
それでは、initializeメソッドへの引数を指定して、インスタンス生成後にたい焼きの「味」と「値段」をターミナルへ出力できるようにしてみましょう。
以下のソースコードをtaiyaki.rbに書き、rubyコマンドで実行してみましょう。
1
2
3
4
5
6
7
class Taiyaki
def initialize(taste, price)
puts "#{taste}味のたい焼きは、#{price}円です。"
end
end
Taiyaki.new("あんこ", 250)
動画のようにtaiyaki.rbを実行すると、あんこ味のたい焼きは、250円
と出力されます。
newメソッドに指定した実引数("あんこ", 250
)は、以下のようにinitializeメソッドで指定する仮引数(taste, price
)へそれぞれ渡されます。
initializeメソッドの中で仮引数を使うことで、渡された値を参照することができます。
次のインスタンス変数で詳しく説明しますが、本来initializeメソッドはインスタンスの初期化の設定を行うことが望ましいです。
今回はinitializeメソッドの引数を説明するために、上記のような使い方をしています。
空のクラスとインスタンス
newメソッドは、指定したクラスのインスタンスを生成して返します。
Taiyakiクラスのインスタンスは、#<Taiyaki:0x00000000014580e8>
のような形式で表現されます。数値の部分はインスタンスごとに異なります。
1
2
3
4
5
class Taiyaki
end
Taiyaki.new
#=> #<Taiyaki:0x00000000014580e8>
上記のTaiyakiクラスのように、設計図に何も書いていない状態でTaiyaki.new
しても、見た目はたい焼きの形だけど皮しかないたい焼き、つまり何も情報をもたないインスタンスが作られるだけです。
このままでは、たい焼きの「味」や「値段」が分かりません。
たい焼き(インスタンス)に情報をもたせるには、「インスタンス変数」を使います。
インスタンス変数について学ぼう
インスタンス変数とは、名前の先頭に@
がついた変数のことです。
1
@taste = "あんこ"
initializeメソッドの中でインスタンス変数を初期化することで、インスタンス生成時に情報をもたせることができます。
1
2
3
4
5
class クラス名
def initialize
@taste = "あんこ"
end
end
たい焼きを作るときに「味」の情報をもたせたい場合は、以下のようにinitializeメソッドの中で@taste
というインスタンス変数を引数を使って初期化します。
引数を使うことで、固定ではなく味を変えてたい焼きを作ることができます。
1
2
3
4
5
6
7
8
class Taiyaki
def initialize(taste)
@taste = taste #@tasteには、引数に渡された値が代入される
end
end
#newメソッドの引数に指定した値は、initializeメソッドの引数に渡される
Taiyaki.new(@tasteに代入する値を指定する)
あんこ味のたい焼きを作ることを考えてみよう
例として、あんこ味のたい焼きを作ることを考えてみましょう。
インスタンス変数の@taste
に代入したい値は"あんこ"
になるので、以下のようにnewメソッドの引数には"あんこ"
を指定します。
1
2
3
4
5
6
7
8
class Taiyaki
def initialize(taste)
@taste = taste
end
end
Taiyaki.new("あんこ")
# => #<Taiyaki:0x0000000002dbf518 @taste="あんこ"> #生成されたインスタンス
Taiyaki.new("あんこ")
によって生成されたインスタンスを確認すると、数値のあとには@taste="あんこ"
が設定されていますね。
このインスタンスには、たい焼きの「味はあんこ」という情報があります。
このようにinitializeメソッドでインスタンス変数を初期化すると、インスタンス生成時に何かしらの情報を持たせることができます。
実際に手を動かしながら、インスタンスが情報を持てるようにしよう!
インスタンス変数を定義しよう
それでは、たい焼きを作るときに「味」や「値段」の情報をもてるように、Taiyakiクラスのinitializeメソッドの中にインスタンス変数を定義してみましょう。
以下のソースコードをtaiyaki.rbに書き、rubyコマンドで実行してみましょう。
1
2
3
4
5
6
7
8
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
end
p Taiyaki.new("あんこ", 250)
動画のようにtaiyaki.rbを実行すると、生成されたインスタンスが出力されます。
※数値の部分はインスタンス毎に異なるので、一致している必要はありません
処理の流れを1つ1つ確認してみましょう。
newメソッドに指定した実引数("あんこ"
, 250
)は、initializeメソッドで指定する仮引数(taste
, price
)へ渡され、インスタンス変数@taste
と@price
にそれぞれ代入されます。
続いて、以下のようにTaiyakiクラスのインスタンスが戻り値として呼び出し元に返ります。
空のクラスと比べてみよう
中身が空のクラスに対してインスタンス生成した場合と比べてみます。
クラスに何も書かれていない状態では、以下のようにTaiyaki.new
しても何も情報をもたないインスタンスが生成されるだけでしたね。
しかし、クラスのinitializeメソッドの中でインスタンス変数を初期化すれば、生成するインスタンスに情報を持たせることできます。
今回は@taste
と@price
を使って、味と値段の情報をインスタンス毎に持たせます。
このようにインスタンスに何か情報を持たせたい場合は、インスタンス変数を使います。
インスタンス変数の特徴として、他にも「クラス内の異なるメソッド間でも値を受け渡せる」「インスタンス毎に固有の値を保持できる」などがあります。
この特徴は、次のインスタンスメソッドを学ぶことによって理解することができます。
次に進む前に必要のない処理を削除しよう
taiyaki.rbのソースコードを編集しましょう。
pメソッドは削除して、変数のanko_taiyaki
にTaiyaki.new("あんこ", 250)
を代入しておきましょう。
1
2
3
4
5
6
7
8
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
newメソッドによって生成されたTaiyakiクラスのインスタンスは、繰り返し利用できるように変数のanko_taiyaki
に代入しておきます。
インスタンスメソッドを定義しよう
インスタンスメソッドとは、クラスのインスタンスに対して呼び出すことができるメソッドのことです。クラスの中でキーワードのdef
を使って普通に定義したメソッドは、インスタンスメソッドとして扱われます。
1
2
3
4
5
class クラス名
def メソッド名
# 処理
end
end
インスタンスメソッドの呼び出しは、以下のように対象のインスタンスにドット(.
)をつなげてメソッド名を指定します。
1
対象のインスタンス.メソッド名
それでは、Taiyakiクラスにインスタンスメソッドを定義していきましょう。
インスタンスメソッドと共にインスタンス変数の特徴も学んでいくよ!
たしかインスタンス変数の特徴は「クラス内の異なるメソッド間でも値を受け渡せる」「インスタンス毎に異なる値を扱える」だったね
インスタンス変数を使って処理を書いてみよう
「インスタンス変数は、クラス内の異なるメソッド間でも値を受け渡せる」ので、インスタンスメソッドの中でもインスタンス変数を利用することができます。
以下のソースコードをtaiyaki.rbに書き、rubyコマンドで実行してみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
anko_taiyaki.show_info
show_info
はインスタンス変数の@taste
と@price
を利用して、インスタンスの保持するたい焼きの味や値段を表示するインスタンスメソッドです。
動画のようにtaiyaki.rbを実行すると、あんこ味のたい焼きは250円
と出力されます。
anko_taiyaki
には、以下のように@taste
と@price
に"あんこ"
と250
が設定されたTaiyakiクラスのインスタンスが代入されています。
このインスタンスが持つ情報は、インスタンス変数を使うことでクラス内の異なるメソッド間でも扱うことができます。
以下のようにanko_taiyaki
に対してshow_infoメソッドを呼び出すと、show_infoメソッド内のインスタンス変数は、anko_taiyaki
が持つ値をそれぞれ参照します。
このようにインスタンスメソッドの中でインスタンス変数を使うと、対象のインスタンスが持つ情報を利用することができます。
インスタンスが保持している情報は、クラス内の異なるメソッドでも共有できます。
インスタンス毎に保持される情報を確かめてみよう
インスタンス変数は、インスタンス毎に異なる値を扱うことができます。
先ほどのanko_taiyaki
には、@taste = "あんこ"
@price = 250
の情報をもつTaiyakiクラスのインスタンスが代入されていますね。
1
2
anko_taiyaki = Taiyaki.new("あんこ", 250)
# => #<Taiyaki:0x00000000026b4840 @taste="あんこ", @price=250>
これはインスタンス生成時に、newメソッドの引数の値でインスタンス変数を初期化しているからでしたね。
以下のようにnewメソッドの引数に"あんこ"
と250
を指定しています。
1
2
3
4
5
6
7
8
9
10
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
#...以下省略
end
#インスタンス変数に代入する値は、newメソッドの引数に指定
anko_taiyaki = Taiyaki.new("あんこ", 250)
newメソッドの引数に指定する値を変更すると、インスタンス変数に"あんこ"
や250
とは異なる情報を設定することができます。
例として、「カスタード味のたい焼き 300円」で考えてみましょう。
newメソッドの引数に"カスタード"
と300
を指定することで、@taste = "カスタード"
@price = 300
の情報をもつTaiyakiクラスのインスタンスが生成されます。
1
2
custard_taiyaki = Taiyaki.new("カスタード", 300)
# => #<Taiyaki:0x00000000009ef980 @taste="カスタード", @price=300
custard_taiyaki
には、この情報を持つインスタンスが代入されます。
このようにインスタンス変数は、インスタンス毎に異なる値を保持することができます。
インスタンス毎にインスタンスメソッドを呼び出してみよう
anko_taiyaki
に対してshow_infoメソッドを呼び出した場合は、「あんこ味のたい焼きは250円です。」と出力されましたね。
1
2
3
4
anko_taiyaki.show_info
# 出力結果
あんこ味のたい焼きは250円です。
それではcustard_taiyaki
に対してshow_infoメソッドを呼び出すと、どのような結果になるでしょうか。
実際にカスタード味のたい焼きを作成して確かめてみましょう。
以下のソースコードをtaiyaki.rbに書き、rubyコマンドで実行してみましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
anko_taiyaki.show_info
custard_taiyaki = Taiyaki.new("カスタード", 300)
custard_taiyaki.show_info
custard_taiyaki
に対してshow_infoメソッドを呼び出した場合は、動画のように「カスタード味のたい焼きは300円です。」と出力されます。
anko_taiyaki.show_info
の出力結果とは違いますよね。
インスタンスメソッドは、インスタンス毎に異なる処理を行うことができます。それはインスタンス変数によって、インスタンス毎に異なる情報を持っているからです。
以下のようにanko_taiyaki
に対してshow_info
を呼び出せば、インスタンスメソッドであるshow_infoのインスタンス変数は"あんこ"
と250
をそれぞれ参照します。
custard_taiyaki
に対してshow_info
を呼び出した場合は、以下のようにインスタンス変数はそれぞれ"カスタード"
と300
を参照します。
このようにインスタンス変数は、生成されたインスタンス毎に共有される変数です。
次に進む前に必要のない処理をコメントアウトしよう
taiyaki.rbのソースコードを編集しましょう。
次のアクセサメソッドではshow_info
は使わないので、以下のように3行をコメントアウトしておきましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
#anko_taiyaki.show_info
#custard_taiyaki = Taiyaki.new("カスタード", 300)
#custard_taiyaki.show_info
アクセサメソッドについて学ぼう
Rubyでは、クラス外部からインスタンス変数に対して直接操作することができません。
以下のようにクラス外部から@taste
を参照したり、変更を行おうとすると、エラーが発生してしまいます。
1
2
3
4
5
6
7
8
9
10
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
anko_taiyaki.@taste
#taiyaki.rb:9: syntax error, unexpected instance variable anko_taiyaki.@taste
1
2
anko_taiyaki.@taste = "栗あん"
# taiyaki.rb:11: syntax error, unexpected instance variable anko_taiyaki.@taste = "栗あん"
クラスの外部からインスタンス変数を参照・変更するには、それを目的としたインスタンスメソッドを定義する必要があります。
ゲッターメソッド
クラスの外部からインスタンス変数の値を参照するインスタンスメソッドのことを「ゲッターメソッド」と呼びます。
ゲッターメソッド名は、それぞれ@
なしのインスタンス変数名を付けます。
クラスの外部から@taste
の値を参照するには、以下のようにゲッターメソッドのtaste
を定義し、呼び出します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
#ゲッターメソッド(@tasteを外部から参照するためのメソッド)
def taste
@taste #"あんこ"を呼び出し元へ返す
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
anko_taiyaki.taste #=> "あんこ"
インスタンス変数は「クラス内の異なるメソッド間でも値を受け渡せる」と学びましたね。
上記ではanko_taiyaki
に対してtaste
を呼び出しているので、tasteメソッド内の@taste
では"あんこ"
を参照することができます。
ゲッターメソッドを経由してインスタンス変数の値を参照できるんだね!
セッターメソッド
インスタンス変数の値をクラスの外部から変更するためのインスタンスメソッドのことを「セッターメソッド」と呼びます。
セッターメソッド名は、@
なしのインスタンス変数名で末尾に=
をつけます。
クラスの外部から@taste
の値を変更するには、セッターメソッドのtaste=
を以下のように定義し、呼び出します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
#セッターメソッド(@tasteを外部から変更するためのメソッド)
def taste=(taste)
@taste = taste
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
anko_taiyaki.taste = "栗あん"
#変更されたか確認する
anko_taiyaki.taste #=> "栗あん"
上記のanko_taiyaki.taste = "栗あん"
では、anko_taiyaki.taste
に"栗あん"
を代入しているようにみえますよね。
実際には、以下のように引数に"栗あん"
を指定してtaste=
を呼び出しています。
1
2
3
4
5
#代入しているようにみえるが...
anko_taiyaki.taste = "栗あん"
#実際にはtaste=メソッドを呼び出している
anko_taiyaki.taste=("栗あん")
セッターメソッドのtaste=
のように、メソッド名の末尾に=(イコール)をつけると、代入式のようにメソッドを呼び出すことができます。
セッターメソッドを経由してインスタンス変数の値が変更できるんだね!
実際に手を動かして、ゲッター / セッターメソッドを定義してみよう
ゲッターメソッド / セッターメソッドを定義してみよう
まずは、クラスの外部から@taste
と@price
の値を参照できるようにゲッターメソッドを定義しましょう。
以下のソースコードをtaiyaki.rbに書き、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
26
27
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
def taste
@taste
end
def price
@price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
p anko_taiyaki.taste
p anko_taiyaki.price
#anko_taiyaki.show_info
#custard_taiyaki = Taiyaki.new("カスタード", 300)
#custard_taiyaki.show_info
taiyaki.rbを実行すると、動画のように"あんこ"
と250
がターミナルへ出力されます。
ゲッターメソッドのtaste
とprice
によって、各インスタンス変数の値を参照できるようになりましたね。
続いて、クラスの外部から@taste
と@price
の値を変更できるようにセッターメソッドを定義しましょう。
anko_taiyaki
がもつ各インスタンス変数の値を"栗あん"
と350
に変更できるように、以下のソースコードをtaiyaki.rbに書き、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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
def taste
@taste
end
def price
@price
end
def taste=(taste)
@taste = taste
end
def price=(price)
@price = price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
p anko_taiyaki.taste
p anko_taiyaki.price
anko_taiyaki.taste = "栗あん"
anko_taiyaki.price = 350
p anko_taiyaki.taste
p anko_taiyaki.price
#anko_taiyaki.show_info
#custard_taiyaki = Taiyaki.new("カスタード", 300)
#custard_taiyaki.show_info
taiyaki.rbを実行すると、動画のように"あんこ"
と250
の後に変更された "栗あん"
と350
がターミナルに出力されます。
セッターメソッドであるtaste=
とprice=
によって、各インスタンス変数の値を変更できるようになりましたね。
attr_accessorメソッド
ゲッターメソッドとセッターメソッドは、参照・変更したいインスタンス変数が増える度に定義する必要があるので、コード量が増えてしまいます。そこで「attr_accessorメソッド」を使うことで、まとめてアクセサメソッドを定義することができます。
attr_accessorメソッドとは、ゲッター / セッターメソッドを自動で定義してくれるメソッドのことです。
以下のように参照と変更したいインスタンス変数名をシンボル、もしくは文字列で指定します。カリキュラムでは、シンボルの指定方法で進めます。
1
attr_accessor :インスタンス変数名
クラスの外部から@age
を参照・変更できるようにしたい場合は、以下のようにクラスの中に定義します。
1
2
3
def クラス名
attr_accessor :age #インスタンス変数名は@なしで指定する
end
上記によって自動で定義されるゲッター / セッターメソッドは、以下の通りです。
1
2
3
4
5
6
7
8
9
# ゲッターメソッド
def age
@age
end
# セッターメソッド
def age=(age)
@age = age
end
複数行にかけて定義していたメソッドが1行で済むので、コードもスッキリとしますね。
これまでTaiyakiクラスでは、@taste
と@price
のゲッター / セッターメソッドをそれぞれ定義しているので、以下のように冗長なソースコードになっています。
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
30
31
32
33
34
35
36
37
38
39
40
41
class Taiyaki
def initialize(taste, price)
@taste = taste
@price = price
end
def taste
@taste
end
def price
@price
end
def taste=(taste)
@taste = taste
end
def price=(price)
@price = price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
p anko_taiyaki.taste
p anko_taiyaki.price
anko_taiyaki.taste = "栗あん"
anko_taiyaki.price = 350
p anko_taiyaki.taste
p anko_taiyaki.price
#anko_taiyaki.show_info
#custard_taiyaki = Taiyaki.new("カスタード", 300)
#custard_taiyaki.show_info
attr_accessorメソッドで、Taiyakiクラスの中をスッキリさせよう!
taiyaki.rbを以下のソースコードのように編集しましょう。
クラスの外部から参照・変更したいインスタンス変数は、@taste
と@price
の2つあるので、attr_accessorメソッドに指定する際にカンマ(,
)で区切ります。
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
attr_accessor :taste, :price
def initialize(taste, price)
@taste = taste
@price = price
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
end
anko_taiyaki = Taiyaki.new("あんこ", 250)
p anko_taiyaki.taste
p anko_taiyaki.price
anko_taiyaki.taste = "栗あん"
anko_taiyaki.price = 350
p anko_taiyaki.taste
p anko_taiyaki.price
#anko_taiyaki.show_info
#custard_taiyaki = Taiyaki.new("カスタード", 300)
#custard_taiyaki.show_info
attr_accessorメソッドを使うことで、Taiyakiクラスのコード量がずいぶんと減りましたね。
最後に問題なく動くかどうかを確かめるために、taiyaki.rbを実行してみましょう。
動画のようにターミナルに出力されたら問題ありません。
クラス変数を定義しよう
クラス変数とは、名前の先頭に@
が2つ付いた変数のことです。
1
@@name = "ぴっかちゃん"
クラス変数には、全てのインスタンスで共有される共通の情報をもたせることができます。
インスタンス変数は「生成されたインスタンス毎に共有される変数」だったのに対して、クラス変数は「全てのインスタンスで共有される変数」です。
たい焼きが全部で何個作られたかわかるように、クラス変数を定義してみましょう。
以下のソースコードのようにtaiyaki.rbにクラス変数の@@total_taiyaki_count
を定義して、たい焼きを作る度にカウントアップさせましょう。
1
2
3
4
5
6
7
8
9
10
11
12
class Taiyaki
attr_accessor :taste, :price
@@total_taiyaki_count = 0
def initialize(taste, price)
@taste = taste
@price = price
@@total_taiyaki_count += 1
end
#...以下省略
end
上記では、Taiyaki クラスの中で@@total_taiyaki_count
を0
で初期化し、initializeメソッドで@@total_taiyaki_count
の値をひとつ加算しています。
initializeメソッドは、newメソッドを呼び出すと自動で呼び出されるメソッドでしたね。
つまり、newメソッドでTaiyakiクラスのインスタンスを生成する(たい焼きを作成する)度に@@total_taiyaki_count
の値がひとつ加算されます。
次のクラスメソッドで、たい焼きが全部で何個作られたかを確認するよ
クラスメソッドを定義しよう
同じクラスから生成されるインスタンスが共通で使用する処理は、クラスの中に「クラスメソッド」というメソッドを定義します。クラスメソッドとは、クラスに対して呼び出すことができるメソッドのことです。
クラスメソッドは、2つの定義方法があります。
1
2
3
4
5
class
def self.クラスメソッド名
# 処理
end
end
1
2
3
4
5
6
7
class クラス名
class << self
def クラスメソッド名
# 処理
end
end
end
クラスメソッドの定義は、どちらの方法でも構いませんが、クラスメソッドをたくさん定義する場合は、定義方法2の方がクラスメソッド名に毎回self.
と付けなくてよいです。
クラスメソッドの呼び出しは、対象のクラスにドット(.
)をつなげてクラスメソッド名を指定します。
1
クラス名.クラスメソッド名
例としてHello!
と挨拶するHello
クラスのクラスメソッドであるgreeting
を定義し、呼び出すには以下のように書きます。
1
2
3
4
5
6
7
8
9
class Hello
# クラスメソッドを定義
def self. greeting
puts "Hello!"
end
end
# クラスメソッドを呼び出す
Hello.greeting #=> Hello!
クラス変数を使って処理を書いてみよう
それでは、たい焼きが全部で何個作られたかを案内してくれるクラスメソッドのshow_all_count
を定義してみましょう。
たい焼きが作成された個数は、先ほど学んだクラス変数の@@total_taiyaki_count
が保持しています。以下のようにtaiyaki.rbにクラスメソッドを追加しましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Taiyaki
attr_accessor :taste, :price
@@total_taiyaki_count = 0
def initialize(taste, price)
@taste = taste
@price = price
@@total_taiyaki_count += 1
end
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
def self.show_all_count
puts "たい焼きは全部で#{@@total_taiyaki_count}個作成されました。"
end
end
続いて、Taiyakiクラス外でnewメソッドを呼び出してインスタンスを生成し、クラスメソッドを呼び出してみましょう。
Taiyakiクラス外の処理は一旦全てコメントアウトして、以下の内容を追加しましょう。
1
2
3
4
5
Taiyaki.new("あんこ", 250)
Taiyaki.new("カスタード", 300)
Taiyaki.new("抹茶", 350)
Taiyaki.show_all_count
動画のようにrubyコマンドでtaiyaki.rbを実行してみましょう。
newメソッドによってTaiyakiクラスのインスタンスを全部で3つ生成したので、ターミナルにはたい焼きは全部で3個作成されました。
と出力されます。
このようにクラスメソッドにクラス変数を使うことで、同じクラスのインスタンスで共有する情報の処理を行えます。
完成したtaiyaki.rbのソースコード
お疲れ様でした!これで「クラスとインスタンス」は終了です。完成のtaiyaki.rbのソースコードをコメントアウトの解説付きで載せておきますので、比較して確認してみてください。
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#たい焼きの設計図を作成
class Taiyaki
#@tasteと@priceのゲッター・セッターメソッドを定義(クラス外から参照・変更可能になる)
attr_accessor :taste, :price
#クラス変数を0で初期化
@@total_taiyaki_count = 0
#newメソッドでインスタンスを生成した際に自動で呼ばれるメソッド
def initialize(taste, price)
#インスタンス変数を引数の値で初期化
@taste = taste
@price = price
#クラス変数の値をひとつ加算させる
@@total_taiyaki_count += 1
end
#インスタンスメソッド
def show_info
puts "#{@taste}味のたい焼きは#{@price}円です。"
end
#クラスメソッド
def self.show_all_count
puts "たい焼きは全部で#{@@total_taiyaki_count}個作成されました。"
end
end
#Taiyakiクラスの外
#Taiyakiクラスのインスタンスを生成
anko_taiyaki = Taiyaki.new("あんこ", 250)
#クラスの外からanko_taiyakiが保持する@tasteと@priceの値を参照
p anko_taiyaki.taste
p anko_taiyaki.price
#クラスの外からanko_taiyakiが保持する@tasteと@priceの値を変更
anko_taiyaki.taste = "栗あん"
anko_taiyaki.price = 350
#クラスの外からanko_taiyakiが保持する@tasteと@priceの値を参照(変更できたか確認)
p anko_taiyaki.taste
p anko_taiyaki.price
#anko_taiyakiに対してインスタンスメソッド呼び出し
anko_taiyaki.show_info
#Taiyakiクラスのインスタンスを生成
custard_taiyaki = Taiyaki.new("カスタード", 300)
#custard_taiyakiに対してインスタンスメソッド呼び出し
custard_taiyaki.show_info
#クラスメソッド呼び出し
Taiyaki.show_all_count
※「クラス変数を使って処理を書いてみよう」で追加したコードは、以下のようにハイライト箇所を不要なため削除してあります。
1
2
3
4
5
Taiyaki.new("あんこ", 250)
Taiyaki.new("カスタード", 300)
Taiyaki.new("抹茶", 350)
Taiyaki.show_all_count
最後にこれまで出てきた用語を整理していこう
オブジェクト指向プログラミングの用語整理
ここまでたくさんの用語が出てきましたが、1つ1つ整理してみましょう。
用語 | 意味/役割 |
---|---|
クラス | オブジェクト指向における設計図 |
インスタンス | クラスから生成された実物体 |
インスタンス変数 ( @変数名 ) |
インスタンス毎に値を保持できる |
クラス変数 ( @@変数名 ) |
クラス内の全てのインスタンスで共有される値 |
インスタンスメソッド | インスタンスに対する操作を行うためのメソッド |
クラスメソッド | クラスに対する操作を行うためのメソッド |
initializeメソッド | 主にインスタンスの初期化の設定を行うためのメソッド |
ゲッターメソッド | クラスの外部からインスタンス変数の値を参照するインスタンスメソッド |
セッターメソッド | インスタンス変数の値をクラスの外部から変更するためのインスタンスメソッド |
attr_accessorメソッド | ゲッター / セッターメソッドを自動で定義してくれるメソッド |
アクセサメソッド | インスタンス変数の参照と変更ができるメソッドの総称 |
この記事のまとめ
- クラスには、設計図としてオブジェクトの振る舞いや状態を設定できる
- インスタンスは、クラスに基づいて生成されたオブジェクトのこと
- クラスに対してnewメソッドを呼び出すと、インスタンス生成できる
この記事で学んだことをTwitterに投稿して、アウトプットしよう!
Twitterの投稿画面に遷移します