メタプログラミングRuby 第4章 まとめ (クラス定義)
class_eval()
- Module#class_eval()とObject#instance_eval()は全くの別物
- instance_eval()はselfに変更を加えるだけ
- class_eval()はselfとカレントクラスに変更を加える
- class()とclass_eval()も違う
- classは束縛を捨てて新しいスコープを作るがclass_eval()はフラットスコープをもつ
- classは定数を必要とするが、class_eval()はクラスを参照する変数なら何でも使える
def add_method_to(some_class) some_class.class_eval do def new_method 'Hello!' end end end add_method_to String "foo".new_method # => "Hello!"
クラスインスタンス変数
class MyClass @my_var = 1 # クラスインスタンス変数 def self.read; @my_bar; end # ①クラスメソッド:クラスインスタンスを参照する def write; @my_var = 2; end # ②インスタンスメソッド:インスタンス変数を設定している def read; @my_var; end # ③インスタンスメソッド:インスタンス変数を参照している end obj = MyClass.new obj.write # ② obj.read # => 2 ③ MyClass.read # => 1 ①
@@v = 1 class MyClass @@v = 2 end @@v # => 2!!
c = Class.new(Array) do def hogehoge "fugafuga" end end MyClass = c c.name # => MyClass
特異メソッド
str = "hoge" def str.title? self.upcase == self end str.title? # => false str.methods.grep(/title?/) # => ["title?"] str.singleton_methods # => ["title?"]
クラスメソッドの構文
###1 class MyClass def self.my_method; end end ###2 def MyClass.my_other_method; end ###3 特異クラスをオープンしてメソッドを定義する class MyClass class << self def my_method end end
module MyModule def self.my_method; "hello"; end end class MyClass include MyModule end MyClass.my_method # NoMethodError! #したのようにすれば動く class MyClass class << self include MyModule end end MyClass.my_method # hello
Extend
- クラスやオブジェクトを拡張するのに特異クラスをオープンするのは自然なことではない。
- 代わりに用意されたのがextend
- レシーバの得意クラスにモジュールをインクルードするためのショートカットである
module MyModule def my_method; 'Hello'; end end obj = Object.new obj.extend MyModule # オブジェクト拡張 obj.my_method # "Hello" class MyClass extend MyModule end MyClass.my_method # "Hello"
大統一理論
- オブジェクトは一種類しかない。それが通常のオブジェクトかモジュールになる。
- モジュールは一種類しかない。それが通常のもモジュール、クラス、特異クラス、プロキシクラスのいずれかになる
- メソッドは一種類しかない。メソッドはモジュール(大半はクラス)にすんでいる
- すべてのオブジェクトはクラス含め、本物のクラスを持っている。それは、通常のクラスか特異クラスになる
- 全てのクラスはスーパークラスを持っている。ただし、Basic Objectにはスーパークラスはない。あらゆるクラスがBasicObjectに向かって一本の継承チェーンを持っている
- オブジェクトの特異クラスのスーパークラスは、オブジェクトのクラスである。クラスの特異クラスのスーパークラスはクラスのスーパークラスの特異クラスである。
- メソッドを呼び出すとき、Rubyはレシーバの本物のクラスに向かって右へ進み、継承チェーンを上へ進む。