ようへいの日々精進XP

よかろうもん

2018 年 05 月 06 日(日)

ジョギング

  • 朝から雨だったのでお休み

日課

  • おやすみ

朝から

雨だったのでダラダラ過ごす. 本当にダラダラ過ごした気がする.

そう言えば, ゴールデンウィークだったんだなって気分だけど, 明日から社会復帰出来るか心配でもある.

お昼に

奥さんが握ってくれたおにぎりにほぐした焼き魚が入っていてとても美味しかった.

今日のるびぃ ~ Ruby技術者認定試験【Gold】模擬問題を解いてみる (re: 13) ~

もう何度か解いているけど, 再び, Ruby技術者認定試験【Gold】模擬問題 を 3 ~ 5 問くらいずつ解いていく.

Q40. Kernel#require メソッド

以下のような file1.rb と file2.rb がある. file2.rb を実行した結果として正しいものを選択する.

# file1.rb
$var += 1

# file2.rb
$var = 0
require "file1.rb"
require "file1.rb"
puts $var
  1. 1

以下, irb による実行例.

irb(main):001:0> $var = 0
=> 0
irb(main):003:0> require './file1.rb'
=> true
irb(main):004:0> require './file1.rb'
=> false
irb(main):005:0> puts $var
1
=> nil

以下, 解説より抜粋.

  • require はライブラリを読み込むメソッド
  • 同一のファイルを指定しても 2 回読み込まれない
  • 対して, load は何度でも読み込むことが出来る

以下, require ではなく, load を利用した場合.

irb(main):001:0> $var = 0
=> 0
irb(main):002:0> load './file1.rb'
=> true
irb(main):003:0> load './file1.rb'
=> true
irb(main):004:0> puts $var
2
=> nil

以下, Kernel#require と Kernel#load の違いについて, ドキュメントから引用.

Kernel.#require は同じファイルは一度だけしかロードしませんが、 Kernel.#load は無条件にロードします。 また、require は拡張子.rb や .so を自動的に補完しますが、 load は行いません。 require はライブラリのロード、load は 設定ファイルの読み込みなどに使うのが典型的な用途です。

Q41. 定数へのアクセス

以下の 2 つのコードの実行結果の出力として正しいものを選択する.

# コード1
class Foo
  Const = "foo"
  def foo
    puts Const
  end
end
Foo.new.foo

# コード2
module M
  def foo
    puts Const
  end
end
class Foo
  Const = "foo"
  include M
end
Foo.new.foo

以下, 解答.

# コード1
foo
# コード2
例外が発生する

以下, irb による実行例.

# コード 1
irb(main):001:0> class Foo
irb(main):002:1>   Const = "foo"
irb(main):003:1>   def foo
irb(main):004:2>     puts Const
irb(main):005:2>   end
irb(main):006:1> end
=> :foo
irb(main):007:0> Foo.new.foo
foo
=> nil
# コード 2
irb(main):001:0> module M
irb(main):002:1>   def foo
irb(main):003:2>     puts Const
irb(main):004:2>   end
irb(main):005:1> end
=> :foo
irb(main):006:0> class Foo
irb(main):007:1>   Const = "foo"
irb(main):008:1>   include M
irb(main):009:1> end
=> Foo
irb(main):010:0> Foo.new.foo
NameError: uninitialized constant M::Const

以下, 解説より抜粋.

  • コード1の foo メソッドはクラス内で定義した定数 Const を参照している為, 定数の値 foo を返す
  • コード2の foo メソッドはモジュール内の未定義定数 Const を参照してしまう為, 例外 (NameError) となる

ちなみに, M#foo から Foo::Const にアクセスする為には, M#foo にて以下のように記述すれば参照出来る.

irb(main):001:0> module M
irb(main):002:1>   def foo
irb(main):003:2>     puts Foo::Const
irb(main):004:2>   end
irb(main):005:1> end
=> :foo
irb(main):006:0> class Foo
irb(main):007:1>   Const = "foo"
irb(main):008:1>   include M
irb(main):009:1> end
=> Foo
irb(main):010:0> Foo.new.foo
foo
=> nil

Q42. undef_method と remove_method

以下の 2 つのコードの実行結果の出力として正しいものを選択する.

# コード1
class Foo
  def foo
    puts "foo"
  end
end
class Bar < Foo
  def foo
    puts "bar"
  end
end
class Bar
  undef_method :foo
end
Bar.new.foo

# コード2
class Foo
  def foo
    puts "foo"
  end
end
class Bar < Foo
  def foo
    puts "bar"
  end
end
class Bar
  remove_method :foo
end
Bar.new.foo

以下, 解答.

# コード1
エラーになる
# コード2
foo

以下, irb による実行例 (抜粋) .

# コード 1
irb(main):011:0> class Bar
irb(main):012:1>   undef_method :foo
irb(main):013:1> end
=> Bar
irb(main):014:0> Bar.new.foo
NoMethodError: undefined method `foo' for #<Bar:0x0055dc2561fc40>
# コード 2
irb(main):011:0> class Bar
irb(main):012:1>   remove_method :foo
irb(main):013:1> end
=> Bar
irb(main):014:0> Bar.new.foo
foo
=> nil

以下, 解説より抜粋.

  • コード1 で foo メソッド は未定義化 (undef_method) されているので, メソッドを呼び出す際に例外となる
  • コード2 では, メソッドの未定義化に remove_method を使用しており, このメソッドはスーパークラスに同名のメソッドがある場合にそれが呼ばれる為, 例外とならない

以下, ドキュメントより引用.

class A
  def ok
    puts 'A'
  end
end
class B < A
  def ok
    puts 'B'
  end
end

B.new.ok   # => B

# undef_method の場合はスーパークラスに同名のメソッドがあっても
# その呼び出しはエラーになる
class B
  undef_method :ok
end
B.new.ok   # => NameError

# remove_method の場合はスーパークラスに同名のメソッドがあると
# それが呼ばれる
class B
  remove_method :ok
end
B.new.ok   # => A

フムフム.