ジョギング
日課
- (腕立て x 50 + 腹筋 x 50) x 3
なんだか
- 頭の中がガチャガチャして集中出来ていない
- 一旦, 色々とリセットしたい気分
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (18) ~
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)
Enumerator オブジェクト
以下のコードの実行結果を得るために __(1)__ に適切なメソッドをすべて選ぶ.
# コード module Enumerable def with_prefix(prefix) return to_enum(__(1)__, prefix) { size } unless block_given? each do |char| yield "#{prefix} #{char}" end end end [1, 2, 3, 4, 5].with_prefix('foobarbaz').reverse_each {|char| puts char } # 実行結果 foobarbaz 5 foobarbaz 4 foobarbaz 3 foobarbaz 2 foobarbaz 1
以下, irb による確認.
# :with_prefix irb(main):001:0> module Enumerable irb(main):002:1> def with_prefix(prefix) irb(main):003:2> return to_enum(:with_prefix, prefix) { size } unless block_given? irb(main):004:2> irb(main):005:2* each do |char| irb(main):006:3* yield "#{prefix} #{char}" irb(main):007:3> end irb(main):008:2> end irb(main):009:1> end => :with_prefix irb(main):010:0> irb(main):011:0* [1, 2, 3, 4, 5].with_prefix('foobarbaz').reverse_each {|char| irb(main):012:1* puts char irb(main):013:1> } foobarbaz 5 foobarbaz 4 foobarbaz 3 foobarbaz 2 foobarbaz 1 => #<Enumerator: [1, 2, 3, 4, 5]:with_prefix("foobarbaz")> # __method__ irb(main):001:0> module Enumerable irb(main):002:1> def with_prefix(prefix) irb(main):003:2> return to_enum(__method__, prefix) { size } unless block_given? irb(main):004:2> irb(main):005:2* each do |char| irb(main):006:3* yield "#{prefix} #{char}" irb(main):007:3> end irb(main):008:2> end irb(main):009:1> end => :with_prefix irb(main):010:0> irb(main):011:0* [1, 2, 3, 4, 5].with_prefix('foobarbaz').reverse_each {|char| irb(main):012:1* puts char irb(main):013:1> } foobarbaz 5 foobarbaz 4 foobarbaz 3 foobarbaz 2 foobarbaz 1 => #<Enumerator: [1, 2, 3, 4, 5]:with_prefix("foobarbaz")>
以下, 解説より抜粋.
- ブロックを渡さない場合は, Enumerator オブジェクトを作成してメソッドをチェーン出来るようにする
- Enumerator オブジェクトを作成するためには, to_enum または, enum_for を呼ぶ
- これら (to_enum 又は enum_for) の引数にメソッド名をシンボルで指定して, チェーン先でブロックを渡されたときにどのメソッドを評価すればよいかが分かる
- 設問では, with_prefix を再評価する必要があるので,
__method__
または:with_prefix
を引数に指定する __method__
はメソッドの中で呼び出すと, そのメソッド名となる
irb(main):014:0> def foobarbaz irb(main):015:1> __method__ irb(main):016:1> end => :foobarbaz irb(main):017:0> irb(main):018:0* p foobarbaz :foobarbaz => :foobarbaz
protected
以下のコードを実行するとどうなるか.
class C protected def initialize end end p C.new.methods.include?(:initialize)
true が表示される
以下, irb にて確認.
irb(main):001:0> class C irb(main):002:1> protected irb(main):003:1> def initialize irb(main):004:2> end irb(main):005:1> end => :initialize irb(main):006:0> irb(main):007:0* p C.new.methods.include?(:initialize) true => true
以下, メモ.
- initialize メソッドは private メソッドである
- protected に設定されたメソッドは, そのメソッドを持つオブジェクトが self であるコンテキスト(メソッド定義式やinstance_eval)でのみ呼び出せる
- Object#methods は, そのオブジェクトに対して呼び出せるメソッド名の一覧を返す, このメソッドは public メソッドおよび protected メソッドの名前を返す
以下, initialize メソッドが private メソッドである確認.
irb(main):001:0> class C irb(main):002:1> def initialize irb(main):003:2> end irb(main):004:1> end => :initialize irb(main):005:0> irb(main):006:0* p C.new.methods.include?(:initialize) false => false
ちなみに, initialize メソッドは, 可視性を public にすることは出来ないが, protected にすることは出来る.
irb(main):001:0> class C irb(main):002:1> public irb(main):003:1> def initialize irb(main):004:2> end irb(main):005:1> end => :initialize irb(main):006:0> p C.new.methods.include?(:initialize) false => false irb(main):007:0> class C irb(main):008:1> protected irb(main):009:1> def initialize irb(main):010:2> end irb(main):011:1> end => :initialize irb(main):012:0> p C.new.methods.include?(:initialize) true => true
フムフム.