ジョギング
日課
- お休み
夕飯
- 初めての「香華」
- 可もなく不可もなく...
今日のるびぃ ~ REx - Ruby Examination にチャレンジ (9) ~
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)
クラス変数
以下のコードを実行するとどうなるか.
class Cls1 @@v = 0 def initialize @@v += 1 end end class Cls2 < Cls1 class << Cls2 @@v += 1 end def initialize @@v += 1 super end end Cls2.new Cls2.new Cls1.new Cls1.new p Cls2.class_variable_get(:@@v)
以下のように各メソッドでどのような値になっているかを出力しながら irb で確認してみる.
class Cls1 @@v = 0 def initialize puts "Cls1 #{@@v}" @@v += 1 end end class Cls2 < Cls1 class << Cls2 puts "Cls2 Class Method #{@@v}" @@v += 1 end def initialize puts "Cls2 #{@@v}" @@v += 1 super end end
以下, irb の実行結果.
irb(main):022:0> Cls2.class_variable_get(:@@v) => 1 irb(main):023:0> Cls2.new Cls2 1 Cls1 2 => #<Cls2:0x005586f67be8a0> irb(main):024:0> Cls2.class_variable_get(:@@v) => 3 irb(main):025:0> Cls2.new Cls2 3 Cls1 4 => #<Cls2:0x005586f67b40a8> irb(main):026:0> Cls2.class_variable_get(:@@v) => 5 irb(main):027:0> Cls1.new Cls1 5 => #<Cls1:0x005586f67a9090> irb(main):028:0> Cls2.class_variable_get(:@@v) => 6 irb(main):029:0> Cls1.new Cls1 6 => #<Cls1:0x005586f679dfb0> irb(main):030:0> Cls2.class_variable_get(:@@v) => 7
- Cls2 にクラスメソッドが定義された時点で +1 となる
- Cls2.new は Cls2 自身の initialize メソッドが呼ばれた時点で +1, 更に super クラスである Cls1.new の initialize が呼ばれて + 1 = 2
- Cls2.new = 2 が計 2 回呼ばれているので, Cls2.new x 2 = 4 となる
- Cls1.new は initialize 時に +1 される
- Cls1.new = 1 が計 2 回呼ばれているので, Cls1.new x 2 = 2 となる
ということで, 最初のクラスメソッド定義時点で 1 + Cls2.new が 2 度呼ばれて 4 + Cls1 が 2 度呼ばれて 2 = 合計 7 となる.
んー, イマイチ...解らない.
Proc
以下のコードを実行するとどうなるか.
def foo(*args, &block) block.call(*args) end foo(1,2,3,4) do |*args| p args.length > 0 ? "hello" : args end
hello を出力される
以下, 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 ? "hello" : args irb(main):007:1> end "hello" => "hello"
以下, 解説より抜粋.
- 1 行目で引数の値を配列として受け取り, ブロックに配列を渡している
- 2 行目で
*
を付けて引数を渡している為, 配列が展開される - 5 行目でブロック変数を渡しているが,
*args
と宣言されている為,[1, 2, 3, 4]
が渡される - 6 行目で
args.length > 0
の結果は真となり,hello
が出力される
ブロックをメソッドの引数として受け取る例. (プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで を参考にして.)
irb(main):001:0> def words(&b) irb(main):002:1> puts 'AAAAA' irb(main):003:1> text = b.call('BBBBB') irb(main):004:1> puts text irb(main):005:1> puts 'CCCCC' irb(main):006:1> endフムフム => :words irb(main):007:0> irb(main):008:0* words do |text| irb(main):009:1* text * 2 irb(main):010:1> end AAAAA BBBBBBBBBB CCCCC => nil irb(main):001:0> def words(*arg, &b) irb(main):002:1> puts 'AAAAA' irb(main):003:1> puts arg irb(main):004:1> text = b.call(*arg) irb(main):005:1> puts text irb(main):006:1> puts 'CCCCC' irb(main):007:1> end => :words irb(main):008:0> irb(main):009:0* irb(main):010:0* words('a', 'b') do |*text| irb(main):011:1* text * 2 irb(main):012:1> end AAAAA a b a b a b CCCCC => nil
フムフム.