load
とrequire
はどう違いますかinclude
とextend
はどう違いますかself
というのは何ですかMatchData
の begin
、end
は何を返しますか同じクラスを再定義すると、前のクラス定義に追加されていきます。 メソッドを再定義した場合には後のものが上書きしますので、前のものは 失われます。
1.6より実装されました。`@@'で始まる変数はクラス変数です。
class Foo @@F = 0 def foo @@F += 1 print @@F, "\n" end end
1.8まで、クラス変数は継承され、子孫クラスからもアクセス可能でしたが、 1.9以降、子孫クラスからはアクセスできなくなる可能性があります。 *1
1.4以前までは定数に代入されたコンテナクラス(Array、Hashなど) がクラス変数の代わりに使用されていました。
class Foo F = [0] def foo F[0] += 1 print F[0], "\n" end end
class Foo @a = 123 # (1) def foo p @a # (2) ... 123でなくnilになる。 end end
(1)がクラスのインスタンス変数、(2)が通常のインスタンス変数です。(2)は
クラスFoo
のインスタンスに属するのに対し、(1)はFoo
というクラ
スオブジェクト(Classのインスタンス)に属します。
インスタンスメソッドからクラスのインスタンス変数に直接アクセスすること はできません。
上のように初期化されていないインスタンス変数とみなされ、nil
になり
ます。
また、クラスのインスタンス変数は継承されず、子孫クラスからはアクセス できません。
特異メソッドは特定のインスタンスに固有のメソッドです。
こんな感じで使います。
foo = Foo.new def foo.hello print "Hello\n" end foo.hello
クラスにあるメソッドを追加したいが、わざわざサブクラスを作るほどのこと でもない、といった場合に有効です。
Javaをやってる人は匿名のインナークラスに似てると思うかもしれませんね。
クラスの特異メソッドをクラスメソッドと呼びます。特異メソッドは オブジェクトの固有のメソッドだと説明したばかりですが、Rubyには、 メタクラスという概念があり、すべてのクラスは、同名のメタクラスと いうものを持っていて、これは、Classクラスのインスタンスになって います。ここにクラスメソッドが定義されます。
形式的にはクラス名をレシーバーとして呼べるメソッドということに なります。
ClassのインスタンスであるFoo
の特異メソッドを考えてみま
しょう。
class Foo def Foo.test print "this is foo\n" end end
呼び出す時はこうです。
Foo.test
何か気付きませんか?
そう、これはいわゆるクラスメソッドですね。
子クラス名をレシーバーとして、親クラスのクラスメソッドを利用することも 可能です。もちろんClassで定義されているメソッドもクラスメソッド として使えます。
すでに特異メソッドについては 触れました。
簡単におさらいするとRubyではオブジェクト(インスタンス)に対してメソッド を追加することができるわけです。
この考えをもう少し進めるとクラスに対する他の操作をオブジェクトに対して も行えるようにしたくなってきませんか?
なってこないよ、と言わないで(^^;
これを可能にするのが特異クラスという機構です。
class Foo def hello print "hello.\n" end end foo = Foo.new foo.hello #=> hello. class << foo attr :name, true def hello print "hello. I'm ", @name, ".\n" end end foo.name = "Tom" foo.hello #=> hello. I'm Tom.
なんかすごいですよね。
ではここで問題。
Q. private_class_method
を使わずにクラスメソッドをprivateにするにはどうすればよいでしょう?
ヒント: クラスメソッドはクラスの特異メソッドでしたね。
ちょっとトリッキーですが、こんなふうにできます。
class Foo # ... end class << Foo def class_method print "class method\n" end private :class_method end Foo.class_method #=> Error
特異メソッドを定義するには、このように特異クラスで定義する方法と 直接 def obj.method という風に定義してしまう方法があります。
ちょっと性格は違いますが、モジュールでは、モジュール関数にする ことにより、特異メソッド(と同時にprivateメソッド)を定義する ことができます。
モジュールの特異メソッドとして、また同時にprivateメソッドして定義されて いるメソッドをRubyではモジュール関数と呼びます。例えば
Math.sqrt(2)
のように用いることも、
include Math sqrt(2)
のようにinclude
して用いることもでき、とても便利です。
あるメソッドをモジュール関数にするには、モジュール定義の中で
module_function :method_name
とします。
モジュールはインスタンスを作れません。 クラスはincludeすることができません。
モジュールは、クラス(モジュール)にincludeされることにより、多重継承に 相当するMix-inを実現します。これは直接の継承であるサブクラスとは 異なりますが、includeしたクラスは、モジュールとis_a?の関係を 持ちます。
前者では定数を直接参照することができます。後者ではクラス名をつけて参照 しなければなりません。
load
とrequire
はどう違いますかどちらも指定した Ruby プログラムを読み込むという点では似ています。しか
し、 load が指定したファイルを Ruby プログラム
として読み込むのに利用するのに対し、 require
では拡張ライブラリの読み込みが可能で、拡張子が so や rb のもののみを
探索します。また require
では拡張子を省略できますし、一度読み込んだ
ファイルは二度と読み込まないようになっています。 load
は指定すれば何度でも読み込みます。
したがって、 require
はライブラリのロードに利用し、 load
は設定ファイ
ルの読み込みなどに使うのが一般的です。また、両者はファイルのサーチパス
も異なります。
include
とextend
はどう違いますかinclude
はmodule
をクラス(モジュール)にインクルードして、
メソッドを関数形式で呼べるようにし、extend
は
module
をオブジェクト(インスタンス)にインクルードして、メソッドを
特異メソッドとして追加します。
self
というのは何ですかself
は、メソッドが適用されるオブジェクトそれ自身を表わします。
関数形式のメソッドは、self
をレシーバーとします。
begin
、end
は何を返しますか$~
に作用して、$0
、$1
などの元の文字列での開始位置、
終了位置を返します。タブ展開の例を参照
してください。
例えば classname = "SomeClass" のときに SomeClass クラスの インスタンスを作りたいというときです。この問題には主に 二通りの解決策があります。
1 は簡単ですしネストしたクラス (Net::HTTP など) にも対応できますが、 CGI 環境などで迂闊に使うと危険です。
一方、2 の方法ではネストしたクラスに対応できません。 次のようにするとネストしたクラスも扱えるようになります。
# Ruby 1.8 以降でいいなら c = classname.split(/::/).inject(Object) {|c,name| c.const_get(name) } c.new # Ruby 1.6 にも対応するなら c = Object classname.split(/::/).each do |name| c = c.const_get(name) end c.new
*1http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9#l39
*2この項目がこのページにあるのはおかしい気がする