ようへいの日々精進XP

よかろうもん

2018 年 04 月 08 日(日)

ジョギング

  • 香椎浜 x 3 周
  • 晴れていたけど, 風が強くて走りづらかった

日課

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

博多デート

  • 奥さんがフェイスエステしている間に, いつもスペースでビール呑みながら作業
  • 夕飯は串匠にて串かつ, 美味しいんだけど, 服に付く匂いが半端ない

Vue.js

  • API レスポンスを SPA で表示したくて, Vue.js のチュートリアルをしている
  • 少し形になってきているので, 近いうちにブログにまとめようと思う 今日の

    今日のるびぃ ~ 定数参照の優先順位 ~

定数参照の優先順についてドキュメントを参考にしつつ, 理解を深めていきたい...

定数の探索順序

  • 親クラスとネストの外側のクラスで同名の定数が定義されている場合, ネストの外側の定数の方を先に参照される
  • 定数参照時の定数の探索順序は, 最初にネスト関係を外側に向かって探索し, 次に継承関係を上位に向かって探索される

以下, ドキュメントより引用.

class Foo
  CONST = 'Foo'
end

class Bar
  CONST = 'Bar'
  class Baz < Foo
    p CONST             # => "Bar"      外側の定数
    # この場合、親クラスの定数は明示的に指定しなければ見えない
    p Foo::CONST        # => "Foo"
  end
end

パッと見, Baz::CONST は, スーパークラスである Foo::CONST の Foo が定義されていると思いそうになるけど, 「ネストの外側の定数が先に参照される」ので, Baz::CONST は Bar となるのか...ナルホド

トップレベルの定数定義

  • トップレベルの定数定義はネストの外側とはみなされない
  • トップレベルの定数は, 継承関係を探索した結果で参照されるので優先順位は低い
  • クラス定義の外 (トップレベル) で定義された定数は Object に所属する

以下, ドキュメントより引用.

class Foo
  CONST = 'Foo'
end

CONST = 'Object'

class Bar < Foo
  p CONST               # => "Foo"
end

# 以下のように明示的にネストしていれば規則通り Object の定数
# (ネストの外側)が先に探索される
class Object
  class Bar < Foo
    p CONST             # => "Object"
  end
end

上記の場合, クラスの継承関係を見てみると...

irb(main):010:0> Foo.ancestors
=> [Foo, Object, Kernel, BasicObject]
irb(main):011:0> Bar.ancestors
=> [Bar, Foo, Object, Kernel, BasicObject

定数の探索は「ネストの外側へ, 次に継承関係を辿る」ということだから, トップレベルの定数 (Object クラスに属する)は優先順位が低くなるということか. ナルホド

継承時の代入について

  • スーパークラスやネスト上位の定数と同名の定数に代入を行うと, 上位の定数への代入ではなく, そのクラスの定数の定義となる

以下, ドキュメントより引用.

class Foo
  CONST = 'Foo'
end
class Bar < Foo
  p CONST               # => "Foo"
  CONST = 'Bar'         # Bar の定数 CONST を*定義*
  p CONST               # => "Bar"  (Foo::CONST は隠蔽される)
  p Foo::CONST          # => "Foo"  (:: 演算子で明示すれば見える)
end

以下, irb による実行例.

irb(main):001:0> class Foo
irb(main):002:1>   CONST = 'Foo'
irb(main):003:1> end
=> "Foo"
irb(main):004:0> 
irb(main):005:0* class Bar
irb(main):006:1>   CONST = 'Bar'
irb(main):007:1>   class Baz < Foo
irb(main):008:2>     p CONST
irb(main):009:2>     CONST = 'Baz'
irb(main):010:2>     p CONST
irb(main):011:2>     p Foo::CONST
irb(main):012:2>   end
irb(main):013:1> end
"Bar"
"Baz"
"Foo"
=> "Foo"

ナルホド