Rubyのクラスを理解する
目次
1.基本知識の確認
1-1.メソッド
1-2.引数
1-3.クラス
1-4.インスタンス
2.クラスで使う呪文達
2-1.インストラクタ(intializeメソッド)
2-2.インスタンス変数(@<変数名>)
2-3.ゲッターとセッター(attr_accessor)
2-4.特殊キーワード(self)
基本知識の確認
クラスの説明をする前に、まずはクラスの中身を説明するために必要な
基本的な単語や知識について記載します。
1-1.メソッド
概要
一言で言うと「関数」のこと、Rubyでは「メソッド」と呼びます。
具体的には実行したい処理をまとめたもの。
クラスメソッドとインスタンスメソッドなどがある。
記述方法
「def」と「end」を書いて、実行したい処理は間に書きます
その後、関数名(defの後に書いた名前)を記述して呼び出し
具体例
メソッド名「hello」、処理は「こんにちは」と出力する関数
def hello
puts "こんにちは"
end
hello
1-2.引数
概要
まずは読み方ですが、引数(ひきすう)と呼びます
具体的には関数などにに、渡す値のことを言います
記述方法
メソッドの後に()をつけて、()内に引数を入れます
具体例
メソッド名「hello」、処理は「こんにちは」と出力する関数
引数に山田を選択して、山田さん、こんにちはと出力させる
def hello(name)
puts "#{name}さん、こんにちは"
end
hello("山田")
1-3.クラス
概要
オブジェクトの設計図となるもの
具体的にはメソッドや変数を定義してまとめたもの
※設計図なので、クラスを作っただけでは実際に処理はできない。
→こんな処理できたらいいよなーって妄想してるだけの状態
記述方法
「class」と「end」で囲む
具体例
クラス名「Greeting」、処理は朝・昼・晩の挨拶を出力する関数
class Greeting
def morning
puts "おはよう"
end
def afternoon
puts "こんにちは"
end
def
puts "こんばんは"
end
end
1-4.インスタンス
概要
クラスを形にしたもの
クラスからインスタンスを生成することで初めて実体になる
イメージとしては妄想を現実にして作ってみたーって感じ
記述方法
クラスを書いた上で、下記のように記載してインスタンスを生成する
→<インスタンス名>=<クラス名>.new
インスタンスにして関数を呼び出すには
→<インスタンス名>.<関数名>
具体例
Greetingクラスを定義する
sampleという名前のインスタンスを生成する
class Greeting
def morning
puts "おはよう"
end
end
sample = Greeting.new #ここでインスタンスを生成
sample.morning #関数を呼び出し
⒉クラス内の呪文達
2-1.コンストラクタ
概要
クラスをインスタンス生成した際に最初に起こる処理
→初期に登録したい固有の状態を登録できる
記述方法
initializeメソッドを使用する
具体例
Greetingクラスにおいて、初期値として「山田」という名前を登録する
class Greeting
def initialize
name = "山田"
end
def morning
puts "#{name}さん、おはよう"
end
end
sample = Greeting.new
sample.moring
以上のコードを書くことで「山田さん、おはよう」と出力される...
と思いきや実は出力されない
実はこのままだとエラーになる。理由は次で説明する
2−2.インスタンス変数
2種類の変数
実は変数には2種類ある。「ローカル変数」と「インスタンス変数」である
「ローカル変数」とは定義した関数でしか使用できない
「インスタンス変数」は他の関数でも使用できる
記述方法
記述方法はとても簡単
・ローカル変数 →<変数名>
・インスタンス変数→@<変数名>
具体例
先ほどのコードを修正する
(さっきのコードだとnameはinitializeメソッドのみでしか使用できないので
moriningメソッドで使用するとエラーになる)
class Greeting
def initialize
@name = "山田"
end
def morning
puts "#{@name}さん、おはよう"
end
end
これでエラーがなく無事に「山田さん、おはよう」と出力されます。
次は引数を使って、山田さん以外の人でも処理できるようにしたいですね。
2-3. ゲッターとセッター
前提
・クラスを作る意味の1つにカプセル化という概念がある
・カプセル化は簡潔にいうと勝手にクラスの中身を取り出したり、
書き換えたりできなくすることである
・デフォルトではクラスの中の変数を取り出したり
書き込んだりはできないようになっている。
ゲッター(getter)
概要
・クラス内に格納された値を取得するためのメソッド
・値を取得できるメソッド関連を総称してgetterと呼ぶ
具体例
nameというインスタンス変数を取得できるゲッターメソッド
class Greeting
definitialize(value)
@name = value
end
#ここからがgetterメソッド
def name
@name
end
#ここまで
end
sample = Greeting.new
sample.name
セッター(setter)
概要
・クラス内に格納されたインスタンス変数に値を書き込むメソッド
・値を書き込めるメソッドを総称してsetterと呼ぶ
具体例
nameというインスタンス変数を書き込めるセッターメソッド
class Greeting
def initialize(value)
@name = value
#ここからがsetterメソッド
def name=(value)
@name = value
end
#ここまで
end
sample =Greeting.new
sample.name("山田")
アクセサ
上記のように、クラス内の変数に処理するには外部アクセスを許可する記述が必要である。
ただ、毎回このように書くのは少し面倒である。
そこで省略できる画期的な記述がアクセサである(3種類あり)
#アクセサ一覧
attr_reader #getterと同様にインスタンス変数を取り出せる
attr_writer #setterと同様にインスタンス変数を設定できる
attr_accessor #getterとsetterの両方の機能を兼ね備えている
先ほどのgetterとsetterは合わせて6行あるが、アクセサを使用すると以下のようになる
class Greeting
attr_accessor :name
def initialize(value)
@name = value
end
end
6行の記述が1行で済むので、使用するのはマストとも言える。
attr_accessorの1行でやっていることをあえて明示するとしたら
・インスタンス変数@nameを作成する
・getterメソッド(name)を定義する
・setterメソッド(name)を定義する
と言えると思う。最後のselfで混乱しないように上記のように機能を分解した。
2-4.selfについて
概要
結論から話すと、その書いているところそのもの(オブジェクト)
英語で言うとit的なニュアンスでその場その場で変わる厄介なもの。
具体例
・クラスメソッド内ではクラス
※クラスメソッド
→インスタンス生成しなくても<クラス名>.<メソッド>で処理できる
インスタンスに関わらず、固有の処理となる
・インスタンスメソッド内ではインスタンス
を表している具体例
class Greeting
def self.class_method #ここでのselfはクラス名Greetingとなる
puts "クラスメソッドです"
end
attr_accessor :name
def initialize(value)
self.name = value #ここではインスタンス名sampleとなる
end
end
Greeting.class_method
sample =Greeting.new("山田")
selfはattr_acsessorとよく一緒に書かれている印象です。
class Greeting
attr_accessor :name , :country
def initialize(input_name,input_country)
self.name = input_name
@country = input_country
end
end
sample = Greeting.new("山田", "日本")
この場合は丁寧に順序立てると
①attr_reader
→インスタンス変数@name、@countryを定義
それぞれname,countryという名前のgetterとsetterを定義
②self.name = name
→setterメソッドのnameを呼び出して引数input_nameを代入
③@country = input_country
→インスタンス変数@countryに直接input_countを代入
結論
selfでも@でも今回の事例で言うとやっていることは同じ
代入の方法が異なる
・selfは関数を呼び出して代入している
・@はインスタンス変数に直接代入している
##まとめ
今回は説明を自分なりに分かりやすくするため変数を区別しました。
実際は引数とインスタンス変数の名前を一緒にして記述されている場合がほとんど。
コードの簡略化などの理由もあるが、初心者の混乱を招く原因の一つだと思う。
今後も自分なりに理解した内容を噛み砕いて記述していければと思う。