ようへいの日々精進XP

よかろうもん

2018 年 02 月 08 日(木)

ジョギング

  • 今日もお休み
  • 腰はだいぶん復旧してきているけど...って感じ

日課

  • こちらも休み
  • そろそろ再開したい

晴れていたけど

  • 底冷えが顕著な一日だった
  • 夕飯は鍋、いつも鍋

今日のるびぃ ~ メソッドの公開レベルについて (3) ~

引き続き, プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで の読書メモ.

protected メソッド

  • メソッドを定義したクラス自身と, そのサブクラスのインスタンスメソッドからレシーバ付きで呼び出すことが出来る

以下のように, weight メソッドを public に公開したくない場合.

class User
  attr_reader :name
  def initialize(name, weight)
    @name = name
    @weight = weight
  end

  def heavier_than?(other_user)
    other_user.weight < @weight
  end

  protected
  def weight
    @weight
  end
end

foo = User.new('Foo', 50)
bar = User.new('Bar', 60)

p foo.heavier_than?(bar) #=> false
p bar.heavier_than?(foo) #=> true

weight メソッドを public に公開しても同様の結果を得ることは出来るが, private メソッドにしてしまった場合には, 以下のレシーバ付きメソッドの呼び出しが出来なくなる.

  def heavier_than?(other_user)
    other_user.weight < @weight
  end

先のサンプルを色々と試してみる.

...
  private
  def weight
    @weight
  end
...

private メソッドにしてみると...以下のように例外.

weight.rb:9:in `heavier_than?': private method `weight' called for #<User:0x005604b35f0b00 @name="Bar", @weight=60> (NoMethodError)
        from weight.rb:24:in `<main>'

話は逸れるけど, foo や bar 等のインスタンス変数やメソッドが呼び出せるかを確認.

...
p foo.instance_variables         #=> [:@name, :@weight]
p foo.respond_to?(:weight, true) #=> true
p bar.instance_variables         #=> [:@name, :@weight]
p bar.respond_to?(:weight, true) #=> true
...
  • Object#respond_to? はオブジェクトがメソッド name を持つとき真を返す
  • メソッドは Symbol または文字列で指定する
  • 第二引数で private メソッドと protected メソッドを確認の対象に含めるかを true か false で指定する

ふむふむ.