自作クラスの親クラスがModuleでもClassでもなくObjectであることが不思議に思えたので、Object, Module, Classの影響を調べてみました。これら3つの関係は下の通りです。
上記3クラスを拡張した場合、互いにどう影響するのでしょうか。
class Object
def self.object_class_method
"object class method"
end
def object_instance_method
"object instance method"
end
end
class Module
def self.module_class_method
"module class method"
end
def module_instance_method
"module instance method"
end
end
class Class
def self.class_class_method
"class class method"
end
def class_instance_method
"class instance method"
end
end
拡張したメソッドが、各クラス、そのインスタンスから呼び出せるか表にまとめました。赤いマルとバツは自分が気になった部分です。
この結果からわかったことを記述していきます。
Classクラスのインスタンスメソッドは全てのクラスメソッド
Object.object_instance_method
Object.module_instance_method
Object.class_instance_method
Object, Moduleのインスタンスメソッドは子孫クラスのClassに引き継がれます。Classのインスタンスは他のクラスになり、全てのクラスでobject_instance_method, module_instance_methodが使えるようになります。class_instance_methodが使える理由も同じです。
インスタンスメソッドが他のクラスのクラスメソッドになるのは、Classクラスのインスタンスが他のクラスになるからです。
Foo = Class.new
# Class.new != Foo.new
Module.object_instance_method
Module.module_instance_method
Module.class_instance_method
Moduleもクラスなので上記と同じ理由でClassのインスタンスメソッドをクラスメソッドとして呼び出すことが出来ます。
Class.object_instance_method
Class.module_instance_method
Class.class_instance_method
こちらが少しややこしいです。全てのクラスはClassから出来ています。Classもクラスなので、Class.newと同じメソッドを持っていることになります。
Class.classでClassが得られることで、自分で自分自身を定義していることが分かります。
Classのインスタンスメソッドは他のクラスのインスタンスから呼び出せない
# 下記のメソッド呼び出しは`new`以外はエラーになります
object = Object.new
object.module_instance_method
object.class_instance_method
foo = Foo.new
foo.module_instance_method
foo.class_instance_method
このため、Classのインスタンスメソッドは他のクラスのインスタンスから呼び出す事ができません。Classクラスのインスタンス、つまりクラスからのみ呼び出すことが出来ます。
Classクラスのクラスメソッドは、他のクラスに受け継がれない。
Foo = Class.new
Foo.object_class_method
# 下記のメソッド呼び出しはエラー
Foo.module_class_method
Foo.class_class_method
クラスは親クラスを指定しない場合は、勝手にObjectクラスが親となります。なのでObjectクラスのクラスメソッドが使えます。
Moduleクラスのクラスメソッドは、その子クラスのClassクラスのクラスメソッドとなります。クラスメソッドなのでClass.newでは使えません。Class.newはクラスであることは先述のとおりです。つまり、Classクラスのインスタンスメソッドは他のクラスに影響しますが、クラスメソッドは影響しません。影響するクラスメソッドは継承したクラスのものです。
自作クラスの親クラスは、ModuleでもClassでもなくObjectである。
自作クラスの親クラスがObjectになるのが不思議でした。ModuleやClassに追加したインスタンスメソッドが自作クラスにも影響がありますよね。これはModuleやClassを継承しているからなのでは?と思いましたが違いました。その理由は下記のとおりです。
-
Classのインスタンスメソッドが、自作クラスのクラスメソッドになる。 - 継承した場合は親のクラスメソッドは、子のクラスメソッドになる。
Classクラスが自作クラスに影響があるのは、継承ではなくクラス自体の仕様を変えているからです。上記2点のせいで少し勘違いをしてしまいました。


