上級のRubyエラー 40問
8種類のエラーを、それぞれ複数パターンずつ収録しています。
- Proc.new の中で return すると LocalJumpError になることがあるProc(Proc.newやKernel#proc)の中でreturnを使うと、そのProcを囲んでいたメソッドから抜けようとします。呼び出し時にすでにそのメソッドの外にいる場合(トップレベルで呼んだ場合など)、戻る先が無くLocalJumpErrorになります。同じ書き方でもlambdaは自分自身から抜けるだけなので、この問題は起きません。
- def self.method と def method を混同すると NoMethodError になるdef self.methodはクラスメソッド(ClassName.methodで呼ぶ)を定義し、def methodはインスタンスメソッド(インスタンス.methodで呼ぶ)を定義します。どちらか一方しか定義していないのに、もう一方の呼び方をするとNoMethodErrorになります。
- coerce未実装のクラスと数値を演算すると TypeError になる自作クラスのインスタンスを 数値 + 自作オブジェクト の順で演算すると、Integer側の+が呼ばれます。Integerは自作クラスの値をどう数値として扱えばよいか分からないため、そのクラスにcoerceメソッドが定義されていない限りTypeErrorになります。
- dup はfreeze状態を引き継がない(clone との違い)freezeしたオブジェクトをdupで複製すると、複製後のオブジェクトはfreezeされていない通常の状態になります。freeze状態も含めて複製したい場合はcloneを使う必要があります。
- 可変長引数を委譲するメソッドで * を付け忘れると ArgumentError になる受け取った可変長引数(*argsで受けた配列)をそのまま別のメソッドに渡すには、呼び出し側でも*を付けて展開する必要があります。*を付けずに渡すと、配列がまるごと1個の引数として渡ってしまい、引数の数が合わずArgumentErrorになります。
- キーワード引数を委譲するメソッドで ** を付け忘れると ArgumentError になる受け取ったキーワード引数(**optionsで受けたハッシュ)をそのまま別のメソッドに渡すには、呼び出し側でも**を付けて展開する必要があります。**を付けずに渡すと、ハッシュが1個の位置引数として渡ってしまい、キーワード引数として認識されずArgumentErrorになります。
- クラス変数 @@var はサブクラスとも共有されてしまう@@で始まるクラス変数は、そのクラスだけでなく継承したサブクラスとも1つの値を共有します。サブクラスごとに独立したカウンタなどを持たせたいつもりで@@変数を使うと、片方のクラスでの変更がもう片方にまで影響します。
- method_missing で super を呼ばないと本来のエラーが消えるmethod_missingを独自定義すると、未定義のメソッド呼び出しをすべて横取りできます。想定していない呼び出しに対してsuperを呼ばずnilなどを返してしまうと、本来出るはずだったNoMethodErrorが出ず、バグが静かに握りつぶされます。