特異クラスによるクラスメソッド定義・class << self ~ end
お金 | 仕事 | 勉強 | プライベート | 健康 | 心
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般
Rubyのクラスは、Classクラスのインスタンスとなっていて、クラス自体も実はオブジェクト。
インスタンスであれば特異メソッドを定義できるわけで、Rubyのクラスメソッドとは、本当はClassクラスインスタンス(クラスオブジェクト)の特異メソッドとなっています。
特異メソッドは、特異クラスに追加する書き方が可能で、以下は特異クラス定義による、クラスの特異メソッド(すなわち、クラスメソッド)を定義する例。
特異クラスにクラスの特異メソッド(クラスメソッド)を定義
class Profile @@count = 0 def initialize(name_one) @name = name_one @@count += 1 end def self.count @@count end attr_accessor :name class << self def singleton_count @@count end end end tom = Profile.new("Tom") p tom puts Profile.count puts Profile.singleton_count david = Profile.new("David") p david puts Profile.count puts Profile.singleton_count nick = Profile.new("Nick") p nick puts Profile.count puts Profile.singleton_count
実行結果
#<Profile:0x283f9f8 @name="Tom"> 1 1 #<Profile:0x283f930 @name="David"> 2 2 #<Profile:0x283f8b8 @name="Nick"> 3 3
ポイントは「class << self ~ end」
ポイントは、Profileクラスの中の、「class << self ~ end」の部分で、ここでのselfは、Profileインスタンス自体(Classクラスのインスタンス)を表している。
クラスの中でのインスタンスメソッド中のselfは、そのクラスのインスタンスを表すけれど、その場合のselfと特異クラス定義のselfは、意味が異なっています。
「class << self ~ end」のselfは、見慣れているクラスメソッド定義の仕方である、「def self.hoge ~ end」の場合のselfと同じ意味で、クラスオブジェクト自体を意味します。
selfの変わりに、クラス名自体(ここでは、Profile)を直書きして、「class << Profile ~ end」と書いても良いが、リファクタリングなどで修正箇所が増えるので、selfを使ったほうが楽だと思います。
「class Profile ~ end」の外側で特異クラス定義
以前、クラス変数・クラスメソッドで、「class Profile ~ end」定義の外側で、Profileの特異クラスを呼び出し、クラスの特異メソッド(クラスメソッド)を追加しようとしたら、クラス変数「@@count」へのアクセスの仕方が分からなかった。
具体的には、以下のようなコード。
class Profile ・・・ end class << Profile def count put "hello" # return @@count #=> これはNameErrorとなった。 #warning: class variable access from toplevel singleton method #NameError: uninitialized class variable @@count in Object end end
今回のように、「class Profile ~ end」の中に、「class << self ~ end」と特異クラスを定義する書き方だと上手く行きました。
上の例の場合でも、@@countにアクセス可能なのかどうか、可能であればその方法を調べる。
- - 関連記事 -
- モジュールの使い方
- クラス定義でメソッドへのアクセス制限・public, private, protected
- クラス継承
- クラス拡張
- クラス変数・クラスメソッド
- アクセスメソッド(アクセサ)をattr_reader, attr_writer, attr_accessorで定義
- アクセスメソッド(アクセサ)
- Rubyのクラス定義・initialize(コンストラクタ)
- スーパークラスとサブクラス・クラス継承
- classメソッド・オブジェクトが属するクラスを調べる
- private, protected アクセス指定の違い
- オブジェクトのコピーを作る
- Rubyのinitializeメソッドの継承