本記事ではメソッド周辺・オブジェクト周辺の文法についてまとめていきます。
まずメソッドについておさらいをします。
メソッド
…Rubyにおけるメソッドとは、特定の動作や処理を定義した一連のコードをまとめたもの。
メソッドを使用することで、コードの再利用ができ、可読性・保守性を向上させることができる。
(→使いたい処理を部品化して簡単に使いまわしができるようにするよ。)
メソッドの特徴
・定義
…defを使用してメソッドを定義する
・呼び出し
…定義したメソッド名をコード内で記載して呼び出す
・引数
…メソッドとその呼び出し元の間でやり取りされる、処理に必要な値
仮引数:メソッド内で定義する仮の引数
(→数学でいうところのx、yとかのイメージ)
実引数:メソッドの呼び出しもとで設定する引数
(→数学でいうところの「代入する値」のイメージ)
・戻り値
…メソッド内の最後の処理によって導き出された結果の値
(→数学でいうところの「=」の右側の値のイメージ)
目次
・Procオブジェクトについて
・yieldについて
・クラス定義について(イニシャライザ・アクセサリ)
Procオブジェクトについて
Procオブジェクト
…do ~ endや中括弧「{}」を用いて処理のブロックを作成したオブジェクトのこと
Procクラスのコンストラクタに、ブロックを指定することで作成できる
コンストラクタ
…クラスのインスタンス(オブジェクト)を生成する際に自動的に呼び出される特別なメソッドのこと
Rubyではコンストラクタはinitializeという名前のメソッドで定義される
コンストラクタは、オブジェクトが生成された際に必要な初期設定や初期化処理を行う
proc = Proc.new{|x| p x}
proc.call(1)
=>1
(例)数値をカウントする際、初期値をプログラムの最初に決定しておいて、後で値を操作したいとき
def get_counter start
# Procオブジェクト作成。引数startには現在の値を設定する
Proc.new{|up| start += up}
end
# 初期値として1を設定。count_upはProcオブジェクトを参照する
count_up = get_counter(1)
# ~~~~~~その他たくさんの長い処理~~~~~~
# count_upの参照するブロックを実行
# procで作成した処理はcallメソッドで呼び出すことができる
count_up.call(1)
=> 2
# ~~~~~~その他たくさんの長い処理~~~~~~
count_up.call(3)
=> 5
また、procを用いるとprocの外にある変数を参照することができるので便利
test = :test1
=> :test1
proc = Proc.new {puts test1}
=> #<Proc:~~~~~~~~~~~~~~~(pry):~>
proc.call
=> test1
# 変数の中身をtest2に変更
test = :test2
=>:test2
# 変更後の変数の中身が表示される
proc.call
test2
=>nil
注意事項
Procオブジェクトの外で指定した変数を、Procで呼び出す場合は
先に変数を定義しておかなければエラーが発生する
yieldについて
yieldを用いるためにまずスコープという概念から説明します。
スコープ
…変数やメソッドが有効でアクセスできる範囲のこと。
スコープによって、変数やメソッドがどこから参照・どこで使用できるかが決まる。
for文、if文、while文ではスコープは作成されない。
ブロックの基本
…ブロックはメソッドを呼び出すときのみ記述でき、
メソッドの内部でyieldという式を使用することで ブロックの内部で記述した処理を
呼び出すことができる。
yield
…メソッド内でブロックを実行するためのもの。
メソッドを呼び出す際にブロックが渡されていると、そのブロックをyieldで呼び出せる。
また、スコープを作成することができる。繰り返し処理を簡潔に記載するのに適している。
def test x
x + yield # ブロックの実行結果を取得(ここでは2)
end
p test(1){ 2 }
=> 3 # ブロック付きメソッドtestの呼び出し
また、下記コードでスコープ作成の流れを確認すると
yieldとは別のブロック内で代入された値は参照できないため、NameErrorが発生している
# スコープが作成されている
def test y
y + yield
end
# ブロック内で代入された値なので、変数xはブロックの外から参照できない
# ブロック内で初期化された変数はブロックの処理が終了すると消滅する
test(1) do
x = 2
end
p x # NameErrorになる
クラス定義について(イニシャライザ・アクセサリ)
クラス定義
…オブジェクト指向プログラミングの基本概念。
クラスを使用して関連するデータ(属性)や動作(メソッド)をまとめ、
オブジェクトを生成するための設計を行うこと
クラス定義の決まり
…クラス名の頭文字は大文字(→小文字から始めると構文エラーになる)
クラス定義の例
class <クラス名>
end
class Test
# initializeメソッドは初期化のときに実行されるメソッド
def initialize(a)
# インスタンス変数を使用することで、値がインスタンスに保持される
@a = a
end
def method1
@a
end
end
# newメソッドの引数はそのまま初期化(initialize)メソッドに渡されるため、
# @aは異なる値で出力される
test1 = Test.new(1)
test2 = Test.new(2)
p foo1.method1 => 1
p foo2.method1 => 2
クラスはオブジェクトであるため、メソッドの実行や変数への再代入が可能
a = Test # Fooの参照先を変数aに代入
a.new(1) # Fooを扱うのと同じように操作できる
Foo = 1 # 定数なので警告が出る
アクセッサ
…クラス内で定義されたインスタンス変数に対して、
ゲッター(読み取り)やセッター(書き込み)のメソッドを簡単に作成するための仕組み。
これを利用することで、インスタンス変数の値を外部から、参照・変更できる
(例)アクセッサを都度定義する例
class Test2
def example
return @example
end
def example=(value) @exampleに対するsetter
@example = value
end
def method; @v3: end
end
test2 = Test2.new
test2.example = 3
p test2.example
=> 3
p test2.method
=> 3
上記ではアクセッサを都度定義していますが、
アクセッサの生成を行うクラスメソッドにより、より簡潔に記載することができます。
attr_reader # getterメソッドの生成を行う
attr_writer # setterメソッドの生成を行う
attr_accessor # getterとsetterメソッドの生成を行う
アクセッサの生成を行うクラスメソッドを使用した場合、コードは以下のようになります。
class Test2
# getterとsetterメソッドの生成を行う
attr_accesser :example
def method; @example; end
end
test2 = Test2.new
test2.example = 3
# 下記はレシーバとなる。インスタンス変数を操作するためmethodから参照が行うことができる
p test2.example
=> 3
p test2.method
=> 3
インスタンス変数は継承されないが、メソッドは継承されるため
サブクラスからメソッドを経由してスーパークラスのインスタンス変数にアクセスすることができます。
class TestSub < Test2
end
testsub = TestSub.new
testsub.example = 4
testsub.example
=> 4