最近のRubyのバージョン

8月半ばにRuby 1.8.7、1.9.1が更新され、1.9.2が正式版になっています。

  • 1.8.6-p399 - 2010/02/04
  • 1.8.7-p302 - 2010/08/16
  • 1.9.1-p430 - 2010/08/16
  • 1.9.2-p0 - 2010/08/18

これらに合わせて、Linuxへのインストールをアップデートしました。

おもなポイント:

undef_methodはクラスにメソッドを追加する?

Module#undef_methodを使うと、「親クラスのメソッドは子クラスで未定義にできる。子クラスで未定義にしたメソッドを孫クラスから呼ぶと未定義になる」ということに気づきました。つまり、「孫→子→親」とメソッドを探すとき、子をスルーして親のメソッドを呼ぶのではなく、子の「未定義」にぶつかるということです。

動作としては自然ですが、どうなっているのでしょう。

続きを読む

「サブクラス化するのは、スーパークラスの実装をよく知っているときに限るべきだ」

Rubyでは、サブクラスで親クラスのprivateメソッドやインスタンス変数を上書きしてしまい、見付けづらいバグを出すことがあります。

このことについて、オライリーの『プログラミング言語Ruby』P248では、次のように述べています(P250も参照)。

Rubyでサブクラス化するのは、スーパークラスの実装をよく知っているときに限るべきだ。クラスのパブリックAPIだけが必要で、その実装は不要なら、クラスを継承するのではなく、カプセル化と委譲によってクラスの機能を拡張すべきだ。

えー。RailsではActiveRecord::BaseやActionController::Baseを継承しないと何もできないのに。

私はRailsのソースはちょくちょく眺めていますが、すべて把握するのは手に負えないし、初心者には「Railsのソース見ろ」は無理な話だし、どうしたものか。

私の経験では、Railsのコントローラで@templateという変数を作って、「何でエラーが出るんだろう」としばらく悩んだことがあります。

Rubyのクラスとモジュールは同じもの

Rubyを覚えるときは、「Rubyにはクラスとモジュールというものがある」と考えるより、「Rubyのクラスとモジュールは(ほとんど)同じもの」と考えるほうが分かりやすいんじゃないかなあ、という気がしてきました。

クラスとモジュールの違いは、次の5つくらい。これ以外はいっしょ。

  • クラスはclass 名前 〜 endで定義する。モジュールはmodule 名前 〜 end で定義する。
  • クラスは継承できる。モジュールはできない。
  • クラスはインスタンスを作成(new)できる。モジュールはできない。
  • モジュールはMixinに使える(include, extendの引数に渡せる)、クラスはMixinに使えない。
  • クラスはClassクラスのオブジェクト、モジュールはModuleクラスのオブジェクト。

「モジュールはクラスの一種」とか「モジュールは特殊なクラス」と考えるのがいいのではないか。ClassクラスはModuleクラスのサブクラスではありますが。

class_eval (module_eval)でのクラス変数とクラス定数

クラス定義の外側で、class_evalのブロックを使ってクラス変数とクラス定数にアクセスしようとすると、Ruby 1.8ではNameErrorが発生します。class_execでも同様です。コードをブロックではなく文字列で渡したときはアクセスできます。

Ruby 1.9.1ではブロック内でもクラス変数・定数にアクセスできるように修正されましたが、1.9.2では1.8と同じ動作に戻されました。

class Foo
  @@var = 123
  VAR = 456
end

Foo.class_eval <<-EOS
  p @@var #=> 123
  p VAR   #=> 456
EOS

Foo.class_eval do
  p @@var #=> NameError(1.8/1.9.2) / 123(1.9.1)
  p VAR   #=> NameError(1.8/1.9.2) / 456(1.9.1)
end

「1.9.2では仕様が1.8に戻る」というのはけっこうありそうな感じです。Rubyリファレンスでは、ここらへんの細かいことは各メソッドのページには載せないで、「細かいこと」専用ページを別に作ろうかと考え中。

参考: