Memento memo.

Today I Learned.

Effective Ruby 第二章 クラス、オブジェクト、モジュール まとめ その2

Effective Ruby 第二章まとめ その1 - Memento memo. の続きです。

Effective Ruby

Effective Ruby

構造化データにはHashではなくStructを使う

  • 新しいクラスを作るほどでもない構造化データを扱う場合はStructを使う
  • Struct::newを定数に代入し、定数をクラスのように扱う
  • ブロックでメソッドも定義できる
Person = Struct::new(:height, :weight, :age) do
  def bmi
    weight / (height * height)
  end
end

hoge = Person.new(1.58, 45, 20)

# getterでアクセスできる
puts hoge.height
# メソッド呼び出し
puts hoge.bmi

Hashで存在しないキーを指定するとnilになってしまってデバッグが辛くなるのでError吐いてくれるStructの方が良さ気です。

モジュールにコードをネストして名前空間を作る

  • 特にライブラリ等を作成する場合は、名前の衝突を避けるためにモジュール内に定義をネストして名前空間を切る。
  • 名前空間の構造はディレクトリに合わせる
  • トップレベル定数( Array とか)を使う場合に曖昧さが残る場合は"::"を使ってフル修飾する( ::Array

ライブラリ使う際は気を付けましょう。普通に開発する場合はあまり気にならないかも?

様々な等値の違いを理解する

  • "==", "===", "equal?", "eql?"の4種類の比較方法がある
  • "equal?"メソッドは厳格にオブジェクト(object_id)を比較する。オーバーライド禁止。
  • "eql?"メソッドはHashキーとして使われているオブジェクトの比較に使われる。たいていの場合は"=="の別名として定義した方が良い。
  • "=="メソッドは2つのオブジェクトが同じ値かどうかを緩やかにテストする。
  • "==="メソッドはcase式のwhen節をテストする。左被演算子がwhenに与えられる引数、右被演算子がcaseに与えられる引数であることに注意。

"<=>"とComparableモジュールで比較を定義する

  • "<=>"演算子を実装し、Comparableモジュールをincludeする
  • "<=>"演算子は、比較できない場合はnilを返す

Version.rb

サンプルはこんな感じでした。

protectedメソッドを使ってprivateな状態を共有する

  • privateな状態はprotectedメソッドで共有する
  • レシーバを明示してprotectedメソッドを呼び出せるのは、同じクラスのオブジェクトか共通のスーパークラスからprotectedメソッドを継承してるオブジェクトだけ

public interfaceは必要最低限にしたいので、関連クラスのオブジェクト間同士の処理はprotectedでの記述を検討しましょう。

クラス変数よりもクラスインスタンス変数を使うようにする

  • クラス変数はグローバル変数と同様の問題(並行処理など)があるため、クラスインスタンス変数を使う。
  • クラスはオブジェクトのため、専用のprivate instance変数セットを持っている。
  • Singletonを作成したい場合は include(Singleton) する