ようへいの日々精進XP

よかろうもん

2018 年 03 月 08 日(木)

ジョギング

  • 雨だったのお休み
  • そろそろ走り出したい...けど, 筋肉痛は続く

日課

  • お休み

バタバタ

  • お仕事...やっぱり, 3 月感がある

夕飯

「オープンにすること」の大切さ

とても良いコラムだった.

geek-out.jp

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

もう何度か解いているけど, Ruby技術者認定試験【Gold】模擬問題 を数問ずつ解いていく. ポイントは, 問題が何について問われているかがちゃんと理解出来ていること.

Q36. メソッドのアクセス制限

メソッドのアクセス制限に関する説明として正しいものを選択してください.

メソッドのアクセス制限を指定しなかった場合、デフォルトでpublicになる

メソッド定義時に以下の三つのアクセス制限を定義出来る.

  • public
  • private
  • protected

アクセス制限を定義しない場合には, デフォルトで public となる.

以下, 実行例. Rubyのprotected methodってどんなときに使うの? を参考にさせて頂いた.

[1] pry(main)> class Foo
[1] pry(main)*   def call_instance_methods  
[1] pry(main)*     public_method    
[1] pry(main)*     protected_method    
[1] pry(main)*     self.protected_method    
[1] pry(main)*     private_method    
[1] pry(main)*     self.private_method    
[1] pry(main)*   end    
[1] pry(main)*     
[1] pry(main)*   def public_method; p 'public_method'; end  
[1] pry(main)*     
[1] pry(main)*   private  
[1] pry(main)*   def private_method; p 'private_method'; end  
[1] pry(main)*     
[1] pry(main)*   protected  
[1] pry(main)*   def protected_method; p 'protected_method'; end    
[1] pry(main)* end  
=> :protected_method
[2] pry(main)> Foo.new.call_instance_methods
"public_method"
"protected_method"
"protected_method"
"private_method"
NoMethodError: private method `private_method' called for #<Foo:0x0000559e73244cc8>
Did you mean?  private_methods
from (pry):7:in `call_instance_methods'
[3] pry(main)> Foo.new.public_method
"public_method"
=> "public_method"
[4] pry(main)> Foo.new.private_method
NoMethodError: private method `private_method' called for #<Foo:0x0000559e731d5da0>
Did you mean?  private_methods
from (pry):20:in `__pry__'
[5] pry(main)> Foo.new.protected_method
NoMethodError: protected method `protected_method' called for #<Foo:0x0000559e73189c20>
Did you mean?  protected_methods
from (pry):21:in `__pry__'
  • private メソッドと protected メソッドはクラス外から直接呼び出すことが出来ない (NoMethodError となる)
  • private メソッドはレシーバ呼び出しが出来ない
  • protected は同一クラス内でのレシーバ呼び出しが可能

Q37. 可変長引数

引数の個数を固定せずに可変長にしたい場合の指定として正しい記述を選択してください.

*引数

メソッドの引数の個数を指定しないで可変長にする場合 *引数 と指定する.

def foo(a, *b); end

以下, 実行例.

[6] pry(main)> def foo(a, *b)
[6] pry(main)*   p a  
[6] pry(main)*   p b  
[6] pry(main)* end  
=> :foo
[7] pry(main)> foo(1, 2, 3, 4, 5)
1
[2, 3, 4, 5]
=> [2, 3, 4, 5]

上記のように, 可変長引数は配列として扱われる.

Q38. ブロック引数

ブロックを受け取るための引数の指定方法として正しい記述を選択してください.

&引数

ブロックを引数として受け取る場合, &引数 と指定する.

def foo(&block);
  block.call('Hello')
end

foo do |text|
  text * 2
end

以下, 実行例.

[18] pry(main)> def foo(&block);
[18] pry(main)*   block.call('Hello')  
[18] pry(main)* end  
=> :foo
[19] pry(main)> 
[20] pry(main)> foo do |text|
[20] pry(main)*   text * 2  
[20] pry(main)* end  
=> "HelloHello"

引数で指定したブロックを call メソッドで呼び出す.

Q39. アクセサメソッド

以下のコードと同様な意味となるコードを選択してください.

# コード
class Foo
 attr_accessor :foo
end

以下のコードが同様の意味となる.

class Foo
  def foo
    @foo
  end
  def foo=(foo)
    @foo = foo
  end
end

その他, 以下のコードについても同様の意味となる.

class Foo
    attr_reader :foo
    attr_writer :foo
end

以下, 実行例. プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで の 7.3.3 のサンプルを参考にした.

[1] pry(main)> class User
[1] pry(main)*   attr_reader :name
[1] pry(main)*   def initialize(name)
[1] pry(main)*     @name = name
[1] pry(main)*   end  
[1] pry(main)* end  
=> :initialize
[2] pry(main)> user = User.new('A')
=> #<User:0x000055f927cd4620 @name="A">
# アクセスは出来るけど...
[3] pry(main)> user.name
=> "A"
# 変更は出来ない...
[4] pry(main)> user.name = 'B'
NoMethodError: undefined method `name=' for #<User:0x000055f927cd4620 @name="A"

attr_writer を以下のように追加すると...

[5] pry(main)> class User
[5] pry(main)*   attr_reader :name
[5] pry(main)*   attr_writer :name
[5] pry(main)* end  
=> nil
[6] pry(main)> user = User.new('A')
=> #<User:0x000055f9280e6100 @name="A">
# インスタンス変数にアクセス出来るし...
[7] pry(main)> user.name
=> "A"
# 変数の変更も出来る
[8] pry(main)> user.name = 'B'
=> "B"
[9] pry(main)> user.name
=> "B"

Q40. require の挙動

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

# file1.rb
$var += 1

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

1

  • require はライブラリを読み込むメソッドで, 同一ファイルを指定しても 1 度しか読み込まれない

以下, 実行例.

$ cat file1.rb 
# file1.rb
$var += 1
$ cat file2.rb 
# file2.rb
$var = 0
require "file1.rb"
require "file1.rb"
puts $var
$ ruby -I . file2.rb 
1

ちなみに, require はファイル名の拡張子を補完してくれる.

$ cat file1.rb 
# file1.rb
$var += 1
$ cat file2.rb 
# file2.rb
$var = 0
require "file1"
require "file1"
puts $var
$ ruby -I . file2.rb 
1

ちなみに, これが load の場合には...

$ cat file1.rb 
# file1.rb
$var += 1
$ cat file2.rb 
# file2.rb
$var = 0
load "file1.rb"
load "file1.rb"
puts $var
$ ruby file2.rb 
2

load を定義した分だけ読み込むことが分かる. そして -I が不要になる.

ふむふむ.