Effective Ruby 第2章まとめ

こんにちは!kossyです!




さて、今回はEffective Rubyの第2章の「覚えておくべき事項」をまとめたものを、
ブログに残してみたいと思います。


第1章のまとめ記事はこちら




第2章 クラス、オブジェクト、モジュール

2-1. Rubyが継承階層をどのように組み立てるかを頭に入れよう

  • Ruby は、クラス階層をサーチするだけでメソッドを見つけられる。探しているメソッドが見つからないときには、method_missing を探して再びサーチを開始する
  • モジュールをインクルードすると、暗黙のうちに特異クラスが作られ、その特異クラスはクラス階層のインクルードしたクラスの上に挿入される
  • 特異メソッド(クラスメソッドと特定のオブジェクト専用のメソッド)は、同じようにクラス階層に挿入される特異クラスに格納される

2-2. superのふるまいがひと通りではないことに注意しよう

  • 継承階層の上位にあるメソッドをオーバーライドするときには、superキーワードを使ってオーバーライドされるメソッドを呼び出すことができる
  • 引数も括弧を付けずにsuperを呼び出すと、呼び出し元のメソッドに渡された全ての引数を渡してオーバーライドされるメソッドを呼び出すのと同じ意味になる
  • オーバーライドされるメソッドに引数を渡さずにsuperを使いたい場合には、super()のように空の括弧を使わなければならない
  • method_missingメソッドを定義してしまうと、super呼び出しが失敗した時に得られる便利な情報が失われてしまう

2-3. サブクラスを初期化する時にはsuperを呼び出そう

  • Rubyは、サブクラスのオブジェクトを作る時に、スーパークラスのinitializeメソッドを自動的に呼び出したりはしない。initializeにも通常のメソッドルックアップの規則が適用され、最初に見つかったバージョンが実行される
  • 明示的に継承を使うクラスでinitiazeメソッドを書く時には、superを使って親クラスを初期化しなければならない。initialize_copyメソッドを定義する時にも、同じ規則が当てはまる

2-4. Rubyの最悪に紛らわしい構文に注意しよう

  • セッターメソッドは、明示的にレシーバを指定しなければ呼び出せない。レシーバがなければ、変数への代入と解釈されてしまう
  • インスタンスメソッドからセッターメソッドを呼び出す時には、レシーバとしてselfを使う
  • セッター以外のメソッドを呼び出す時には明示的にレシーバを指定する必要はない。selfでコードを汚さないようにしよう

2-5. 構造化データの表現にはHashではなくStructを使おう

  • 新しいクラスを作るほどでもない構造化データを扱う時には、HashではなくStrictクラスを使うようにしよう
  • Strict::newの戻り値を定数に代入し、その定数をクラスのように扱おう。

2-6. モジュールにコードをネストして名前空間を作ろう

  • モジュール内に定義をネストして名前空間を作ろう
  • 名前空間の構造は、ディレクトリ構造と同じにしよう
  • トップレベル定数を修飾無しで使うと曖昧になる時には、::を使ってフルに修飾しよう

2-7. さまざまな等値の違いを理解しよう

  • equal?メソッドをオーバーライドしてはならない。このメソッドは、厳格にオブジェクトを比較し、両方がメモリ内の同じオブジェクトを指すポインタ出ない限り(つまり、両者がともに同じobject_idを持たない限り)trueを返さないという動作をすべきものと考えられている
  • Hashクラスは、衝突が起きたときに、キーとして使われているオブジェクトを比較するためにeql?メソッドを使っている。デフォルト実装は、おそらく望ましい動作をしない
  • 2つのオブジェクトが同じ値かどうかをテストするときには == 演算子を使う。数値を表すクラスなど、一部のクラスは型変換を実行する緩やかな等値演算子を持っている
  • case式は、個々のwhen節をテストするために === 演算子を使っている。左被演算子はwhenに与えられる引数、右被演算子はcaseに与えられる引数である

2-8. <=>とComparableモジュールで比較を実装しよう

  • オブジェクトの順序は、<=>演算子を定義し、Comparableモジュールをincludeして実装しよう
  • <=>演算子は、左被演算子が右被演算子と比較できないものならnilを返す
  • クラスのために<=>を実装した場合、特にインスタンスをハッシュキーとして使うつもりなら、eql?を==の別名にすることを検討しよう。別名にする場合は、hashメソッドもオーバーライドしなければならない。

2-9. protectedメソッドを使ってプライベートな状態を共有しよう

  • プライベートな状態はprotectedメソッドで共有する。関連するクラスの間でプライベートな情報を共有する目的がある
  • レシーバを明示してprotectedメソッドを呼び出せるのは、同じクラスのオブジェクトか共通のスーパークラスからprotectedメソッドを継承しているオブジェクトだけだ

2-10. クラス変数よりもクラスインスタンス変数を使うようにしよう

  • クラス変数よりもクラスインスタンス変数を使うようにしましょう
  • クラスはオブジェクトなので、専用のプライベートなインスタンス変数セットを持っている。


出典: https://www.shoeisha.co.jp/book/detail/9784798139821