見出し画像

initialize と attr_accessor [Ruby]

今回note初投稿になります ٩( ᐛ )و

Rails の実装などをしていると定期的に見かけるが、はっきりと理解できていない2つのメソッド、initializeattr_accessor

上記2つのメソッドをちゃんと理解したいと思い、それぞれ調べたのでその軌跡をここにまとめておきたいと思います。
なおここでまとめた内容は基本的に Ruby の仕組みの話であり、Rails の話は出て来ません。(これを調べるまで自分自身RubyとRailsがごっちゃになっていた。)

またこれらの理解に利用したのは、伊藤 淳一 著の Ruby のチェリー本です。(やっぱり分かりやすい)
https://www.amazon.co.jp/プロを目指す人のためのRuby入門-言語仕様からテスト駆動開発・デバッグ技法まで-Software-Design-plusシリーズ/dp/4774193976

Rubyのクラスとオブジェクト

表題のメソッドの話の前に、Ruby のクラスとオブジェクト の話を少しだけしておきます。これらの理解が表題の2つのメソッドの理解に必要になります。

クラスとは

クラスはよく「オブジェクトの設計図」と呼ばれることがあります。
例えば車の設計図があり、そこから黒い車や赤い車が作成されたとします。作成された車たちがオブジェクトであり、車の設計図がクラスとなります。
ちなみにRubyでは全てがオブジェクトであり、それらは必ず何かのクラスに属しています。クラスが同じであれば、オブジェクトの保持するデータ項目や使えるメソッドは同じになります。

オブジェクトはnewメソッドで作成できる

Rubyのクラスの定義の仕方とそのクラスからオブジェクトを作成する方法を以下に示します。オブジェクトはnewメソッドで作成することができす。

# Userクラス
class User
    # Userクラスが保持するデータや、利用できるメソッドをこの中に定義
end

# Userオブジェクトを作成
User.new
#=> <User:2x907g29b434ra0>

これらの知識を前提に、以下でinitializedとattr_accessorについて解説していきます。

オブジェクトと intialize メソッド

結論initializeとは、オブジェクト作成時に発火されるプライベートメソッドです。

initialize メソッド

前項で説明した通り、オブジェクトはnewメソッドで作成できますが、その時に呼ばれるメソッドがinitialize メソッドです。
Rubyが標準で提供するメソッドであり、オブジェクトを初期化する際に実行したい処理があれば、この中に書きます。

class User
    # newされた際に'Hello world!!'とログを吐かせる
    def initialize
        puts 'Hello world!!'
    end
end

User.new
#=> Hello world!!

initialize メソッドに引数を渡す

initializeに引数を追加した場合、オブジェクトの作成時、つまりnewメソッドにも引数が必要になります。

class User
    def initialize(name)
        # 引数をインスタンス変数@nameに保存。(インスタンス変数については次説明
        @name = name
    end
end

# initializeに合わせて引数を1つ渡す
User.new('John')
#=> #<User:1y249sc42d355cc6@name="John">

ちなみにintializeはデフォルトでプライベートメソッドになっている為、外部から呼び込むことはできません。

インスタンス変数とアクセサメソッド

結論attr_accessorとは、それぞれのオブジェクトが持つインスタンス変数を外部から参照・変更するためのメソッド、アクセサメソッドです。
attr_accessorの理解がは少し込み入ってるのですが、その理解にはRubyのオブジェクトにおけるインスタンス変数と、その変数へのゲッター・セッターと言ったアクセサメソッドの理解が必要です。

インスタンス変数

インスタンス変数とは、同じオブジェクトで共有される変数のことで、@変数名の形で定義します。先ほどのinitializeでは、引数を@nameというインスタンス変数に格納していますが、格納された@nameはそのオブジェクト内で共通して利用できます。

例えばUserクラスに以下のようなhelloメソッドがあった場合、それぞれ返り値が異なりますが、それはそれぞれのオブジェクトに格納されたインスタンス変数の値が異なるからです。

# Userクラスのインスタンスメソッド
def hello
    puts "Hello, #{@name}"
end

user_john = User.new('John')
user_mike = User.new('Mike')
user_john.hello
#=> Hello, John
user_mike.hello
#=> Hello, Mike

アクセサメソッド

上記で説明した通り、initializeメソッドで引数をインスタンス変数に格納することで、その値をそれぞれのオブジェクト内で共有できます。しかしインスタンス変数はクラス外からは参照できません(コンソールや他のメソッドなど)。

なのでその値を参照する為には、変数を返すだけのメソッドを定義しなければいけません。また同様にインスタンス変数の値を変更するには、変更するだけのメソッドを定義しなければいけません。

# それぞれインスタン変数@nameの場合
# インスタンス変数の値を返すだけ    = ゲッター
def name
    @name
end

# インスタンス変数に値を変更するだけ = セッター
def name=(value)
    @name = value
end

前者の参照専用メソッドをゲッターと言い、後者の変更専用メソッドをセッターと言います。それぞれのインスタンス変数にアクセスする為のメソッド、アクセサメソッドと言います。

attr_accessor

ただインスタンス変数毎に、上記のようなセッター・ゲッターを設定するととても冗長なコードができます。
そこでRubyが提供しているのがattr_accessorメソッドになります。以下の様にattr_accessorを設定することで、外部から指定のインスタンス変数にアクセスできる様になります

class User
    attr_accessor :name

    def initialize(name)
        @name = name
    end
end

なお参照のみ可能にする場合は attr_reader、変更のみ可能にする場合はattr_writerを利用するとそれぞれ制限できます。

おわりに

長々と説明してきましたが、この記事の流れえ通り順を追って紐解くことでやっとそれぞれのメソッドを理解することができました。

ただ今回この記事を書く背景として、RubyのClassとModuleについて理解したいと考えました。それらを理解するにあたり、initializeとattr_accessorの理解が明確になったので、今回まとめようと思いました。

なので次はRubyのClassとModuleについてまとめようと思います。最後までお読み頂きありがとうございました!

この記事が気に入ったらサポートをしてみませんか?