ようへいの日々精進XP

よかろうもん

2018 年 03 月 16 日(金)

ジョギング

  • 休み
  • 左膝の内側が痛い...よー

日課

  • (腕立て x 50 + 腹筋 x 30) x 3

夕飯

  • 俺達の「よしもと」
  • 奥さんの生誕ウィークなのでちょっとだけ贅沢
  • 「よしもと」の愛想がイイ兄ちゃんが三月一杯で辞めるとのことで、出会いと別れの三月なんだなと実感

今日のるびぃ ~ Ruby 技術者認定試験 Gold を受験した方の記事を参考にして (1) ~

今日の参考

http://d.hatena.ne.jp/rightgo09_ruby/20121226/p1 を参考にさせて頂いた. 有難うございます.

クラスメソッドの継承

クラスメソッドは継承されるのか.

class Foo
  class << self
    def foo
      "foo"                                                                                                       
    end 
  end 
end

class Bar < Foo
end

以下, 実行例.

[1] pry(main)> class Foo
[1] pry(main)*   class << self  
[1] pry(main)*     def foo    
[1] pry(main)*       "foo"                                                                                                             
[1] pry(main)*     end       
[1] pry(main)*   end     
[1] pry(main)* end  
=> :foo
[2] pry(main)> 
[3] pry(main)> class Bar < Foo
[3] pry(main)* end  
=> nil
[4] pry(main)> Foo.foo
=> "foo"
[5] pry(main)> Bar.foo
=> "foo"

クラスメソッドも通常のインスタンスメソッドのように継承される.

super を利用した include したモジュールの同名メソッド呼び出し

  • モジュールを include すると, スーパークラスとの間に無名クラスが挿入される

という前提で...

モジュールメソッド内で super を利用すると, スーパークラスの同名メソッドを呼ぶことが出来る.

module M
  def foo
    puts "module M"
    super
  end
end

class Foo
  def foo
    puts "class Foo"
  end
end

class Bar < Foo
  include M                                                                                                             
  def foo
    puts "class Bar"
    super
  end
end

以下, 実行例.

...
[6] pry(main)> Bar.ancestors
=> [Bar, M, Foo, Object, PP::ObjectMixin, Kernel, BasicObject]
[7] pry(main)> Bar.new.foo
class Bar
module M
class Foo
=> nil

定数の探索 (const_missing)

Foo クラス内で Object クラスの const_missing を定義することが出来る.

class Foo
  def Object.const_missing(name)
    p "Missing const name is #{name}"
  end
end

以下, 実行例.

[8] pry(main)> class Foo
[8] pry(main)*   def Object.const_missing(name)  
[8] pry(main)*     p "Missing const name is #{name}"    
[8] pry(main)*   end    
[8] pry(main)* end  
=> :const_missing
[9] pry(main)> A
"Missing const name is A"
=> "Missing const name is A"
[11] pry(main)> Foo::B
"Missing const name is B"
=> "Missing const name is B"

例えば, 以下のようにも定義することが出来るけど, ちょっと挙動が異なる.

[1] pry(main)> class Foo; end
=> nil
[2] pry(main)> class Bar
[2] pry(main)*   def Foo.const_missing(name)
[2] pry(main)*     "Missing const name is #{name}"
[2] pry(main)*   end  
[2] pry(main)* end  
=> :const_missing
[3] pry(main)> Foo::A
=> "Missing const name is A"
[4] pry(main)> Bar::B
NameError: uninitialized constant Bar::B
from (pry):8:in `__pry__'

ん, と一瞬思ったけど...

[5] pry(main)> Bar.ancestors
=> [Bar, Object, PP::ObjectMixin, Kernel, BasicObject]

Object クラスを継承しているんだけど, 当然, const_missing は定義していないので, 上記のような結果となる.

[6] pry(main)> class Bar
[6] pry(main)*   def Object.const_missing(name)
[6] pry(main)*     "Missing const name is #{name}"
[6] pry(main)*   end  
[6] pry(main)* end  
=> :const_missing
[7] pry(main)> Foo::A
=> "Missing const name is A"
[8] pry(main)> Bar::B
=> "Missing const name is B"

再オープンして, Object クラスに const_missing を再定義してあげることで, 冒頭と同じ挙動となる.

ふむふむ.