ようへいの日々精進XP

よかろうもん

2018 年 02 月 26 日(月)

ジョギング

  • お休み
  • 土日にムリした感があったので

日課

  • お休み
  • ストレッチ

夕飯

  • この野菜の値段が高騰している時に実家からキャベツや白菜が送られてきていたので, 久しぶりに鍋
  • 両親に感謝

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

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

Q11. クラスメソッド

以下のコードの実行結果から__(1)__に当てはまるものを選択してください.

# コード
class Foo
  def __(1)__
   puts "foo"
 end
end
Foo.foo


# 実行結果
foo

Foo.foo

  • クラスメソッドはクラスをレシーバにして呼び出すことが出来る
  • クラスメソッドは クラス.メソッド の形式で定義出来る

クラスメソッドは以下のような方法で定義出来る.

# パターン (1) 全てのクラスで有効になる
class Class
  def method1;end
end

# パターン (2) コーディング規約 (https://shugo.net/ruby-codeconv/codeconv.html) 的には誤った例らしい
class Foo
  def Foo.method1;end
end

# パターン (3) クラス定義内での self はそのクラス自身を指すので...
class Foo
  def self.method1;end
end

# パターン (4) 特異クラスの再オープンを使う
class Foo
  class << self
    def self.method1;end
  end
end

Q12. self キーワード

以下のコードを実行した結果を選択してください.

class Foo
  def foo
    self
  end
end
class Bar < Foo
  def bar
    foo
  end
end
p Bar.new.bar.class

Bar

  • Bar は Foo を継承している為, bar メソッドは foo メソッドを呼び出すことが出来る
  • foo メソッドの self は bar メソッドを呼び出した Bar クラスのオブジェクトを参照する
  • このオブジェクトに対して class メソッドが呼ばれるので Bar が返される

Q13. private メソッド

以下の実行結果にならないようにするために__(1)__に当てはまるものを選択してください.

# コード
class Foo
  def bar
    self.foo
  end
  __(1)__
  def foo
    puts "foo"
  end
end
Foo.new.bar

# 実行結果
foo

private

  • private メソッドだと, レシーバ付き呼び出しが出来ない
[1] pry(main)> class Foo
[1] pry(main)*   def bar  
[1] pry(main)*     self.foo    
[1] pry(main)*   end    
[1] pry(main)*   private  
[1] pry(main)*   def foo  
[1] pry(main)*     puts "foo"    
[1] pry(main)*   end    
[1] pry(main)* end  
=> :foo
[2] pry(main)> Foo.new.bar
NoMethodError: private method `foo' called for #<Foo:0x000055e881776f40>
from (pry):3:in `bar'

Q14. Enumerable#inject

以下のコードの実行結果から__(1)__に当てはまるものを選択してください.

# コード
puts [1,2,3].__(1)__


# 実行結果
6

inject(0){|sum, i| sum + i }

  • inject メソッドは引数で初期値を取り, レシーバの要素の先頭から順にブロック内の処理を実行し結果を求めていくメソッド
[3] pry(main)> puts [1, 2, 3].inject(0){|sum, i| sum + i }
6
=> nil
# 以下のようにも記述出来る
[9] pry(main)> p [1, 2, 3].inject(:+)    
6
=> 6

以下のように Array#each を利用して書くことも出来る.

[6] pry(main)> sum = 0
=> 0
[7] pry(main)> puts [1, 2, 3].each {|v| sum += v }
1
2
3
=> nil
[8] pry(main)> p sum
6
=> 6

Q15. Object#freeze

以下のコードの実行結果として正しいものを選択してください.

# コード
char = { :a => "A" }.freeze
char[:a] = "B"
p char

例外発生

  • freeze メソッドはオブジェクトを変更不可能にするメソッド
  • ハッシュオブジェクトの値を変更 char[:a] = "B" でエラーが発生する

freeze メソッドはオブジェクトを変更不可にするが, オブジェクトの要素の変更は可能.

# String オブジェクトを freeze
[5] pry(main)> str = 'a b c d'.freeze
=> "a b c d"
# オブジェクトの各要素は変更可能 (大文字に変更している)
[6] pry(main)> str.upcase
=> "A B C D"
# オブジェクトに対して変更 (要素を追加) しようとすると例外となる
[7] pry(main)> str.concat('e')
FrozenError: can't modify frozen String

以下のように破壊的な変更は出来ないが, 別の配列を参照するように変更は可能.

[1] pry(main)> ary = [1, 2, 3]
=> [1, 2, 3]
[2] pry(main)> ary << 4
=> [1, 2, 3, 4]
[3] pry(main)> ary.freeze
=> [1, 2, 3, 4]
[4] pry(main)> ary << 5
FrozenError: can't modify frozen Array
from (pry):4:in `__pry__'
[5] pry(main)> ary += [5, 6]
=> [1, 2, 3, 4, 5, 6]

ほうほう... object_id が変わるらしい.

[1] pry(main)> ary = [1, 2, 3]
=> [1, 2, 3]
[2] pry(main)> ary.object_id
=> 47377624999920
[3] pry(main)> ary.freeze
=> [1, 2, 3]
[4] pry(main)> ary.object_id
=> 47377624999920
[5] pry(main)> ary += [5, 6]
=> [1, 2, 3, 5, 6]
[6] pry(main)> ary.object_id
=> 47377624250560