ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
やらかした...
- ギョームで障害発生...うーん...ごめんなさい
- ということで, 終日, 調査や検証等...
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (28) ~
REx - Ruby Examination の問題を自分なりにアレンジした上で 1 〜 3 問くらいずつ解いていく. 正直言ってかなり難しい. 尚, irb に動作確認環境は以下の通り.
$ ruby --version ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux] $ irb --version irb 0.9.6(09/06/30)
クラスやモジュールの優先順位
以下のコードを実行するとどうなるか.
module Mod1 end module Mod2 end class Cls include Mod1 include Mod2 end p Cls.ancestors
[Cls, Mod2, Mod1, Object, Kernel, BasicObject]
以下, irb による確認.
irb(main):001:0> module Mod1 irb(main):002:1> end => nil irb(main):003:0> irb(main):004:0* module Mod2 irb(main):005:1> end => nil irb(main):006:0> irb(main):007:0* class Cls irb(main):008:1> include Mod1 irb(main):009:1> include Mod2 irb(main):010:1> end => Cls irb(main):011:0> irb(main):012:0* p Cls.ancestors [Cls, Mod2, Mod1, Object, Kernel, BasicObject] => [Cls, Mod2, Mod1, Object, Kernel, BasicObjec
以下, 解説より抜粋.
include
はモジュールのメソッドをインスタンスメソッドとして追加する- メソッドの探索順は
self
の後に追加される - 複数回
include
された場合には, 後から宣言されたモジュールのメソッドが優先される (設問では Mod2 のメソッドが優先される)
Module#ancestors
について, ドキュメントより抜粋.
クラス、モジュールのスーパークラスとインクルードしているモジュールを優先順位順に配列に格納して返します。
以下, irb による実行例.
irb(main):001:0> module Foo irb(main):002:1> end => nil irb(main):003:0> class Bar irb(main):004:1> include Foo irb(main):005:1> end => Bar irb(main):006:0> class Baz < Bar irb(main):007:1> p ancestors # スーパークラスとインクルードしているモジュールの優先順位を返す irb(main):008:1> p included_modules # インクルードしているモジュールを返す irb(main):009:1> p superclass # スーパークラスを返す irb(main):010:1> end [Baz, Bar, Foo, Object, Kernel, BasicObject] [Foo, Kernel] Bar => Bar
ブロック引数の渡し方
以下のコードを実行するとどうなるか.
def foo(&block, *args) block.call(*args) end foo(1,2,3,4) do |*args| p args.length > 0 ? "AAA" : args end
例外が発生する
以下, irb にて確認.
irb(main):001:0> def foo(&block, *args) irb(main):002:1> block.call(*args) irb(main):003:1> end SyntaxError: (irb):1: syntax error, unexpected ',', expecting ')' def foo(&block, *args) ^ (irb):3: syntax error, unexpected keyword_end, expecting end-of-input
以下, 解説より抜粋.
- ブロック引数は仮引数の中で最後に記述する
- ブロック引数はメソッド定義につき 1 つしか指定出来ない
- 他の引数がある場合には, ブロック引数は必ず最後に指定する必要がある
以下, 正しく動作するコード.
def foo(*args, &block) block.call(*args) end foo(1,2,3,4) do |*args| p args.length > 0 ? "AAA" : args end
以下, irb にて確認.
irb(main):001:0> def foo(*args, &block) irb(main):002:1> block.call(*args) irb(main):003:1> end => :foo irb(main):004:0> irb(main):005:0* foo(1,2,3,4) do |*args| irb(main):006:1* p args.length > 0 ? "AAA" : args irb(main):007:1> end "AAA" => "AAA"
フムフム.