IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

RubyビギナーのためのStep upコラム

CTC 教育サービス

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  Microsoft Azure  Docker  Kubernetes 

第12回 クラスインスタンス変数と特異クラス・特異メソッド(3) (中越智哉) 2019年2月

みなさん、こんにちは。
前回、前々回に引き続きのコラムですが、今回は特異クラスについて紹介します。

前回、「特異メソッド」について取り上げました。

特異メソッドによってクラスインスタンスを含む特定のインスタンスに対してメソッドを追加できるということがわかりましたが、オブジェクト指向の考え方では、メソッドはクラスに属するものであり、特異メソッドといえども、どこかのクラスには属していないといけないような気がしてしまいますよね。

そのような、特異メソッドを含むようなクラスとして生成されるのが、特異クラスです。
ただ、特異クラスは用途がかなり限定的(特異メソッドを利用するときのみ必要になる)なため、あまり直接的に表に出てくることはありません。

さて、ここに至って、こんなことを思われた方はいらっしゃらないでしょうか。特異クラスそれ自体を定義することは可能なのだろうか?と。

実は、可能です。といいますか、特異メソッドを定義する際の記法としてよく用いられている

class << インスタンス
end

という書式は、Rubyでは「特異クラス定義式」と呼ばれるもので、指定したインスタンスの内容と同じ構造を初期状態として持つ特異クラスを定義していることになります。

クラスメソッドはクラスインスタンスに属する特異メソッドですが、上記の形式でのクラスメソッドの定義は「<<」の後ろにクラスインスタンスを指定し、その「クラスインスタンスの特異クラスを定義している」とみることができるわけなのですね。

しかしながら特異クラスはその定義書式から見ても分かるように表面上は無名のクラスで識別子を持ちませんから、そのままでは定義後に直接参照する手段がありません。

もし、どうしても特異クラス自身のクラスインスタンスを参照したい場合は、「singleton_class」メソッドを実行すれば、定義後であっても特異クラスのインスタンスの参照を得ることができます。

また、あるクラスにどのようなメソッドが定義されているかは、インスタンスメソッドであれば「instance_methods」メソッドを(継承されたものを含めない場合は引数をfalseにする)、特異メソッドであれば「singleton_methods」メソッドを使います。

これらをまとめて、動作確認してみましょう。以下のようなコードを実行してみます。
Fooというクラスを定義し、そのインスタンスに対して特異メソッドを定義(同時に特異クラスのインスタンスが作られる)したのちに、それぞれの情報を表示させています。

fig01

これを実行すると、以下のような結果が表示されます。

fig02

fooやfoo.singleton_classをpメソッドに渡すと、それぞれのクラスのinspectメソッドの戻り値が表示されますが、fooとfoo.singleton_classのinspectメソッドの戻り値が異なることから、両者が同一のインスタンスでないことがわかります。

さらに、クラスFooのインスタンスメソッド(継承したものを除く)の一覧を表示させると「hello」メソッドが、インスタンスfooの特異メソッドの一覧を表示させると、「goodbye」メソッドが表示されます。インスタンスfooの特異メソッド(foo.singleton_methods)
は、インスタンスfooの特異クラスのインスタンスメソッド(foo.singleton_class.instance_methods(false))と同義ですから、これを表示すると、やはり「goodbye」となります。

前々回、前回、今回と続いた一連のコラム、きっかけはインスタンス変数を定義する箇所の話から始まりましたが、それを少し深堀してみることで、Rubyのオブジェクト指向は非常に綿密に整理されたものであることがおわかりいただけたかと思います。

それでは、次回のコラムもお楽しみに。

 


 

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  Microsoft Azure  Docker  Kubernetes