知っておくべきこと
Rubyにおけるクラスとは
Rubyにおけるクラス定義は「コードを実行する」ということだ。JavaやC#ではクラスを定義してもそのクラスのオブジェクトを生成して、メソッドを呼び出すまで何も起きない。しかし、Rubyでクラスを定義するということはオブジェクトの動作を規定することではなく、コードを実行するということなのだ。
クラスインスタンス変数 & クラス変数
クラスインスタンス変数
1 2 3 | |
こういうふうにクラスにもインスタンス変数が定義できる。ここの@my_varはクラス定義の中にあるのでクラスに属している。
だからクラスのオブジェクトのインスタンス変数とは別物ということだ。
1 2 3 4 5 6 7 8 9 10 11 12 | |
上記のコードには2つのインスタンス変数を定義している。どちらも@my_varという名前だ。しかし、それぞれ異なるスコープに定義されており、別々のオブジェクトに属している。上記のコードのMyClassのオブジェクトのobjはMyClassクラスのインスタンス変数の@my_varは呼べない。同じくobjの外側からもobjのインスタンス変数の@my_varが呼べないのだ。
こういうふうにクラスがselfとなる場所に定義されているインスタンス変数をクラスインスタンス変数と呼ぶ。
クラス変数
クラス変数は@@をつけて定義できる。
1 2 3 | |
これはクラスインスタンス変数とは違う。サブクラスや通常のインスタンスメソッドからもアクセスできる。
1 2 3 4 5 | |
しかし、クラス変数の使いには少し気をつけないといけないところがある。
1 2 3 4 5 6 7 | |
@@vの値が変わるのはこのクラス変数がクラスではなく、クラス階層に属しているからだ。@@vはmainのコンテキストに定義されているので、mainのクラスであるObjectの全ての子系にも属しているということになり、全部同じクラス変数を共有しているからだ。
特異メソッド
特異メソッド
Rubyでは、特定のオブジェクトにメソッドを追加できる。
1 2 3 4 5 6 7 8 9 | |
上記のコードはtitle?メソッドを文字列strに追加している。Stringクラスの他のオブジェクトには影響はない。
こうしたあるオブジェクトに特化したメソッドのことを特異メソッドと呼ぶ。
クラスメソッドの真実
クラスメソッドはクラスの特異メソッドである。
1 2 3 4 5 6 7 | |
上記の2つの定義は同じものなのだ。
1 2 3 | |
上記のobjectの部分にはオブジェクトの参照、クラス名の定数、selfのいずれかが使える。つまり、クラスメソッドはselfを使った特異メソッドである。
クラスマクロ
Module#attr_*()族のメソッドを使えば、一気にオブジェクトに対するアクセサを生成できる。
Module#attr_readerは読み取り用、Module#attr_writerは書き込み用、Module#attr_accessorは読み書き両用だ。
コードで見てみると
1 2 3 4 5 | |
NoMethodErrorが出てしまう。
1 2 3 4 5 6 7 8 9 | |
nameのメソッドは読み込めるが、アクセスはできない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
これでインスタンス変数の@nameにアクセスできる。
これはこうもかける。
1 2 3 4 | |
そして、
1 2 3 4 5 6 7 8 9 10 11 | |
こう使える。
このようなメソッドをクラスマクロと呼ぶ。
クラスマクロはキーワードのように見えるが、クラス定義の中で使えるクラスメソッドである。
&Check
&Checkでのクラスメソッド
formクラスでよくクラスメソッドを使っている。
- 例
1 2 3 4 5 6 7 8 9 10 11 | |
&Checkでのクラスマクロ
form, service, usecaseなどで幅広く使われている。(attr_accessor, attr_reader)
- 例
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 | |
全然関係ないけど気になるやつ
delegate
上記のコードの中でdelegateというのがあったけど、delegateは何物か気になったから調べておく。
delegateはhas_one, throughと似たようなもので、toで指名しているオブジェクトからの関係あるモデルを呼び出せるらしい。
上記ではtoで:burdenを指名しているから、:burdenの関係モデルの中のcommenterを持ってこれる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
上記のコードでわかるように渡されるburdenはQualitative::SurveyGroupCommentのオブジェクトである。
だから、delegateを使ってQualitative::SurveyGroupCommentオブジェクトの関係モデルのcommenterオブジェクトを呼び出すことができるということだ。
1
| |
のように使える。
次の記事
第4章 クラス定義の残った分量の
- 特異クラス
- アラウンドエイリアス
あと、
- 第5章「コードを記述するコード」