ようへいの日々精進XP

よかろうもん

2018 年 07 月 31 日 (火)

ジョギング

  • 香椎浜 x 2 周
  • なんかギクシャクしている感じ

日課

  • お休み

長田さんと

長田さんと, 奥さんと三人で博多で串カツをつつきながら一杯. クラウドの話や, AS400 の話等, 色々な話をさせて頂いて楽しい時間を過ごすことが出来た. 今度は人生の相談とかもできればと考えている.

頭痛とか肩こりとか

  • 朝からキツイ

今日のるびぃ ~ Ruby 技術者認定試験合格教本 (Silver/Gold 対応) Ruby 公式資格教科書 基礎力確認試験 (1) オブジェクト指向 (1) ~

irb に動作確認環境は以下の通り.

$ ruby --version
ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-linux]
$ irb --version
irb 0.9.6(09/06/30)

オブジェクト指向 (1)

Q12. 以下の実行結果になるように, [ x ] に記述する適切なコードを選べ.

# コード
class Super
  def greet
    'Hello'
  end
end

class Sub < Super
  def greet
    [ x ] + 'World.'
  end
end

puts Sub.new.greet

# 実行結果
Hello World.

以下, 解答.

  1. super

以下, irb にて確認.

irb(main):001:0> class Super
irb(main):002:1>   def greet
irb(main):003:2>     'Hello'
irb(main):004:2>   end
irb(main):005:1> end
=> :greet
irb(main):006:0> 
irb(main):007:0* class Sub < Super
irb(main):008:1>   def greet
irb(main):009:2>     super + 'World.'
irb(main):010:2>   end
irb(main):011:1> end
=> :greet
irb(main):012:0> 
irb(main):013:0* puts Sub.new.greet
HelloWorld.
=> nil

以下, 解説より抜粋.

オブジェクト指向 (2)

Q13. 以下のコードを実行した時, 何が出力されるか.

module M
  def foo
    self.class
  end
end

class C
  include M
end

p C.new.foo

以下, 解答.

  1. C

以下, irb にて確認.

irb(main):001:0> module M
irb(main):002:1>   def foo
irb(main):003:2>     self.class
irb(main):004:2>   end
irb(main):005:1> end
=> :foo
irb(main):006:0> 
irb(main):007:0* class C
irb(main):008:1>   include M
irb(main):009:1> end
=> C
irb(main):010:0> 
irb(main):011:0* p C.new.foo
C
=> C

以下, 解説より抜粋.

  • include は, モジュールをクラスに mix-in する
  • C.new.foofoo メソッドを呼び出すと, foo メソッド内の selfC.new で生成されたオブジェクト自身を返すので, self.classC を表す

オブジェクト指向 (3)

Q14. 以下のコードを実行するとどうなるか.

module Mod
  def foo
    puts 'Mod'
  end
end

class Cls1
  include Mod
  def foo
    puts 'Cls1'
    super
  end
end

class Cls2 < Cls1
  def foo
    puts 'Cls2'
    super
  end
end

Cls2.new.foo

以下, 解答.

  1. Cls2 Cls1 Mod

以下, irb にて確認.

... 略
irb(main):022:0* Cls2.new.foo
Cls2
Cls1
Mod
=> nil

以下, 解説より抜粋.

  • メソッドは, 自クラス→インクルードしているモジュール→スーパークラススーパークラスのインクルードしているモジュールの順番に検索される
  • 設問において, Cls2 クラスのオブジェクトで foo を呼び出すと, Cls2 クラスの foo が実行され Cls2 が出力される
  • Cls2#foo の super で Cls1#foo を呼び出し, Cls1 を出力される
  • 更に, Cls1#foo の super で Mod#foo を呼び出して, Mod を出力する

以下, メソッド探索色々.

# メソッド探索色々 (1)
module Mod
  def foo
    puts 'Mod'
  end
end

class Cls1
  include Mod
  def foo
    puts 'Cls1'
  end
end

Cls1.new.foo #=> 'Cls1'

# 以下, irb にて確認.
... 略 ...
irb(main):013:0> 
irb(main):014:0* Cls1.new.foo
Cls1
=> nil

引き続き, 探索.

# メソッド探索色々 (2)
module Mod
  def foo
    puts 'Mod'
  end
end

class Cls1
  include Mod
  def foo
    puts 'Cls1'
    super
  end
end

Cls1.new.foo

# 以下, irb にて確認.
... 略 ...
irb(main):014:0> 
irb(main):015:0* Cls1.new.foo
Cls1
Mod
=> nil

さらに探索.

module Mod
  def foo
    puts 'Mod'
  end
end

class Cls1
  def foo
    puts 'Cls1'
  end
end

class Cls2 < Cls1
  include Mod
  def foo
    puts 'Cls2'
    super
  end
end

Cls2.new.foo

# 以下, irb にて確認.
... 略 ...
irb(main):020:0> Cls2.new.foo
Cls2
Mod
=> nil
irb(main):021:0> Cls2.ancestors
=> [Cls2, Mod, Cls1, Object, Kernel, BasicObject]

さらに探索.

module Mod
  def foo
    puts 'Mod'
  end
end

class Cls1
  include Mod
  def foo
    puts 'Cls1'
    super
  end
end

class Cls2 < Cls1
  include Mod
  def foo
    puts 'Cls2'
    super
  end
end

Cls2.new.foo

# 以下, irb にて確認.
... 略 ...
irb(main):022:0> Cls2.ancestors
=> [Cls2, Cls1, Mod, Object, Kernel, BasicObject]
irb(main):023:0> Cls2.new.foo
Cls2
Cls1
Mod
=> nil

上記, 面白い例. include すると super クラスの間に挿入されるはずなので,

Cls2
Mod
Cls1

と出力されると予想したけど...子クラスで include したモジュールが無視されているように見える.

オブジェクト指向 (4)

Q15. 以下のコードを実行するとどうなるか.

class Cls1
  def Cls1.foo
    puts 'Cls1'
  end
end

class Cls2 < Cls1
  def foo
    puts 'Cls2'
  end
end

Cls2.foo

以下, 解答.

  1. Cls1 と表示される

以下, irb にて確認.

... 略 ...
irb(main):013:0* Cls2.foo
Cls1
=> nil

以下, 解説より抜粋.

  • Cls2.foo はクラスメソッド foo を呼び出す
  • Cls2#fooインスタンスメソッドの為, Cls1 のクラスメソッド foo が実行される

オブジェクト指向 (5)

Q16. 以下のコードを実行するとどうなるか.

module M1; end
module M2; end
class Cls1
  include M1
end
class Cls2 < Cls1
  p self.ancestors
  include M2
end

以下, 解答.

  1. [Cls2, Cls1, M1, Object, Kernel, BasicObject]

以下, irb にて確認.

irb(main):001:0> module M1; end
=> nil
irb(main):002:0> module M2; end
=> nil
irb(main):003:0> class Cls1
irb(main):004:1>   include M1
irb(main):005:1> end
=> Cls1
irb(main):006:0> class Cls2 < Cls1
irb(main):007:1>   p self.ancestors
irb(main):008:1>   include M2
irb(main):009:1> end
[Cls2, Cls1, M1, Object, Kernel, BasicObject]
=> Cls2

以下, 解説より抜粋.

  • ancestors は, クラス, モジュールの優先度で配列に格納して返す
  • Cls2 クラスの include M2 は ancestors 実行後の為, ancestors の対象外となる

フムフム.