メタプログラミングRuby 第2版, Effective Rubyのオブジェクト階層・クラス定義などを2、3周読んで、わかったかも!なポイントを書きます。
とりあえずその辺のトピックスを1周して「と・・・特異・・クラス・・?」と恐れおののいた人の理解の助けになれば・・なメモ。
オブジェクト
- Rubyではすべてのものがオブジェクトである
- クラスもオブジェクトである
- Rubyでたくさん存在しているクラスは、 Classクラスのオブジェクト である
クラス
- クラスとはモジュールである
- モジュールとクラスの違い、モジュールは
new
できない - つまりモジュールはインスタンス化できない
モジュール
- モジュールのインスタンスメソッドは、クラスに
include
されると、__インスタンスメソッド__として呼びだせる - モジュールのインスタンスメソッドは、クラスに
extend
されると、__クラスメソッド__として呼びだせる - モジュールの__クラスメソッド__は、クラスに
include
してもextend
しても呼び出せない - モジュールのクラスメソッドはモジュールの__特異クラス__に存在するから
include
- モジュールを クラス に取り込むための機構
extend
- モジュールを オブジェクト に取り込むための機構
- Rubyの全てのクラスは Classクラスのオブジェクト なので、
extend
でクラスを拡張できる - Classクラスのオブジェクト を拡張するための仕組みが 特異クラス
includeとextendの例
module MyModule
def my_instance_method
'my_instance_method'
end
def self.my_class_method # 呼び出せない
'my_class_method'
end
end
class MyIncludeClass
include MyModule
end
my_include_class = MyIncludeClass.new
my_include_class.my_instance_method
# => "my_instance_method"
class MyExtendClass
extend MyModule
end
MyExtendClass.my_instance_method
# => "my_instance_method"
メソッド
- メソッドは1種類である
- いろいろ種類があるじゃないかと思うが、どこに存在しているかの違い
インスタンスメソッド
- オブジェクトから呼びだせるメソッド
- オブジェクトのクラスに存在する
クラスにインスタンスメソッドを定義する例
class MyIncludeClass
def my_method1
'my_method1'
end
end
※ class
はすでに定義済みのクラス名(例ではMyIncludeClass)が渡されると、再オープンする。オープンしたクラスにメソッドを def
で追加している。
インスタンスメソッドを呼び出してみる例
m1 = MyIncludeClass.new
m1.my_method1
=> "my_method1"
上の例で MyIncludeClass
は include MyModule
しているので、モジュールのメソッドと、今追加したメソッドがインスタンスメソッドとして定義されている。
定義済みのインスタンスメソッドを確認する例
MyIncludeClass.instance_methods # インスタンスメソッド一覧を表示
# => [:my_method1, :my_instance_method, ...]
クラスメソッド
- クラスから呼びだせるメソッド
- Classクラスのオブジェクト = クラス の特異クラスに存在する
クラスにクラスメソッドを定義する例
class MyExtendClass
def self.my_extend1
'my_extend1'
end
end
※ def self
とするとクラス定義の中の self
つまりそのクラス自身をレシーバとしたメソッドが定義できる = クラスメソッド
クラスメソッドを呼び出してみる例
MyExtendClass.my_extend1
=> "my_extend1"
上の例で MyExtendClass
は extend MyModule
しているので、モジュールのメソッドと、今追加したメソッドがクラスメソッドとして定義されている。
定義済みのクラスメソッドを確認する例
irb> MyExtendClass.singleton_methods
# => [:my_extend1, :my_instance_method]
特異クラス
- すべての オブジェクト が裏に持つことができる特別なクラス
- 特異クラスはオブジェクトを 1つしか持てない
- ので singleton_class ともいう
- オブジェクトの特異クラスに存在するメソッドは、オブジェクトの 特異メソッド である
- オブジェクト特異メソッドは、オブジェクトのクラスのメソッド(クラスメソッド)である
- つまりクラスは Classクラスのオブジェクト なので、 Classクラスのオブジェクトの__特異クラス__ に定義されたメソッドはそのクラスだけで使える クラスメソッド である
特異クラスの確認方法 : singleton_class
irb> my_extend_class = MyExtendClass.new
=> #<MyExtendClass:0x007f8c2384cb08>
irb> my_extend_class.singleton_class
=> #<Class:#<MyExtendClass:0x007f8c2384cb08>>
特異メソッドの確認方法 : singleton_methods
irb> my_extend_class.singleton_class.singleton_methods
=> [:my_extend1, :my_instance_method]
特異クラス側からメソッドを確認
irb> MyExtendClass.singleton_class.instance_methods
# => [:my_extend1, :my_instance_method, ...]
特異クラスはオブジェクト階層のどこに入る?
- 特異メソッドの住処が特異クラス
- オブジェクトが特異メソッドを持っていれば、まず特異クラスからメソッド探索される
- 特異クラスもオブジェクト階層に組み込まれる
- 特異クラスの
superclass
はオブジェクトの通常のクラス - 継承したサブクラスからもクラスメソッドが使えるようになる
特異クラスのsuperclassの確認方法
irb> my_extend_class.singleton_class.superclass
# => MyExtendClass
これらのポイントを頭の片隅に置きつつ、もう一度 「メタプログラミングRuby」 を読むとRubyわからん・・の闇がパッと晴れる・・!かも。。