Posted at

自作クラスの親クラスはModuleでもClassでもなくObjectである

More than 3 years have passed since last update.

自作クラスの親クラスが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.classClassが得られることで、自分で自分自身を定義していることが分かります。


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になるのが不思議でした。ModuleClassに追加したインスタンスメソッドが自作クラスにも影響がありますよね。これはModuleClassを継承しているからなのでは?と思いましたが違いました。その理由は下記のとおりです。



  • Classのインスタンスメソッドが、自作クラスのクラスメソッドになる。

  • 継承した場合は親のクラスメソッドは、子のクラスメソッドになる。

Classクラスが自作クラスに影響があるのは、継承ではなくクラス自体の仕様を変えているからです。上記2点のせいで少し勘違いをしてしまいました。