ジョギング
- 体調はイマイチだったが、汗を少しかいたら楽になるかなと思って走った
- 香椎浜 x 2 周
- 左膝の内側、同足底筋も痛い...
日課
- お休み
体調
- やっぱり、終日辛い感じだった
夕飯
- 元気つけようと思って、久しぶりにざいとんで台湾ラーメンと餃子
今日のるびぃ ~ Ruby 技術者認定試験 Gold 演習問題を解いていく (6) ~
もう何度か解いているけど, Ruby 技術者認定試験合格教本 の演習問題と模擬試験を数問ずつ解いていく. ポイントは, 問題が何について問われているかがちゃんと理解出来ていること.
Q16. オブジェクト指向
以下のコードを実行するとどうなるか.
module M1; end module M2; end class Cls1; include M1; end class Cls2 < Cls1 p self.ancestors include M2 end
以下のように出力される (はず).
[Cls2, Cls1, M1, Object, Kernel, BasicObject]
以下, irb での実行例.
[Cls2, Cls1, M1, Object, Kernel, BasicObject] => Cls2
以下, 解説とドキュメントより抜粋.
- クラス, モジュールのスーパークラスとインクルードしているモジュールを優先順位順に配列に格納して返す
- Cls2 クラスの
include M2
は ancestors 実行後の為, ancestors 対象外となる - モジュールの機能追加は、クラスの継承関係の間にそのモジュールが挿入されることで実現される
- メソッドの探索などはスーパークラスよりもインクルードされたモジュールのほうが先に行われる
例えば, 以下のようなコードだとどうなるか.
module M1; end module M2; end class Cls1; include M1; end class Cls2 < Cls1 include M2 end Cls2.ancestors
スーパークラスよりもインクルードされたモジュールの方が先にメソッド探索されるということなので, 以下のようになる.
[Cls2, M2, Cls1, M1, Object, Kernel, BasicObject]
実際に irb で試してみる.
irb(main):007:0> Cls2.ancestors => [Cls2, M2, Cls1, M1, Object, Kernel, BasicObject]
LGTM.
Q17. オブジェクト指向
以下のコードを実行すると何が表示されるか.
module M1; end module M2; end class Cls1; prepend M1; end class Cls2 < Cls1 prepend M2 end Cls2.ancestors
以下のように出力される (はず)
[M2, Cls2, M1, Cls1, Object, Kernel BasicObject]
以下, irb での実行例.
irb(main):007:0> Cls2.ancestors => [M2, Cls2, M1, Cls1, Object, Kernel, BasicObject]
以下, ドキュメントと解説より抜粋.
- prepend は指定したモジュールを self の継承チェインの先頭に追加することで self の定数, メソッド, モジュール変数を「上書き」する
- prepend の引数として渡したモジュールのインスタンスメソッドで super を呼ぶことで self のモジュール/クラスのメソッドを呼び出すことが出来る
- prepend されたモジュールは, prepend した対象のクラスより先にメソッドの探索が行われるように継承関係が作られる
ちなみに, 以下のコードを実行した場合にどうなるか.
module M1 def foo puts 'M1#foo' super end end class Cls1 def foo puts 'Cls1#foo' end end class Cls2 < Cls1 prepend M1 def foo puts 'Cls2#foo' end end Cls2.new.foo
以下のようになるはず.
M1#foo Cls2#foo
irb で実行してみる.
irb(main):020:0> irb(main):021:0* Cls2.new.foo M1#foo Cls2#foo => nil
prepend の引数として渡したモジュールのインスタンスメソッドで super を呼ぶことで self のモジュール/クラスのメソッドを呼び出すことが出来るということから, 上記のように Cls2 の同名メソッド (Cls2#foo) を呼ぶことが出来ている.
Q18. オブジェクト指向
以下の実行結果になるように, [ x ] に記述する適切なコードを全て選ぶ.
Class Example def hoge self.piyo end [ x ] def piyo puts 'piyo' end end Example.new.hoge
以下, 実行結果.
piyo
piyo がレシーバ付きで呼びだされている点に注目すると, [ x ] で定義することが出来るコードは以下となる (はず).
- protected
- public
- 何も記述しない
以下, irb での実行結果の抜粋.
# protected irb(main):011:0> Example.new.hoge piyo # public irb(main):011:0> Example.new.hoge piyo # 何も記述しない irb(main):021:0> Example.new.hoge piyo # private だと... irb(main):011:0> Example.new.hoge NoMethodError: private method `piyo' called for #<Example:0x0055acdca4ac98>
private 指定されたメソッドはレシーバ付きで呼び出すことが出来ない.
ふむふむ.