07 August 2013
お先にどうぞ ─ Rubyのモジュールにおける譲る心をあなたにも知ってほしい
─問題─
Ruby2.0におけるモジュールに関し次の問に答えよ(各5点、制限時間5分)。
問1
以下のコードにおける出力を答えよ。
class A
def initialize
print :a
super
end
def initialize
print :A
super
end
end
A.new
問2
以下のコードにおける出力を答えよ。
module B
def initialize
print :B
super
end
end
class A
include B
def initialize
print :A
super
end
end
A.new
問3
以下のコードにおける出力を答えよ。
module C
def initialize
print :C
super
end
end
module B
def initialize
print :B
super
end
end
class A
include C
include B
def initialize
print :A
super
end
end
A.new
問4
以下のコードにおける出力を答えよ。
module C
def initialize
print :C
super
end
end
module B
def self.included(base)
base.send :include, C
end
def initialize
print :B
super
end
end
class A
include B
def initialize
print :A
super
end
end
A.new
問5
問4における状態から最小の改変で出力をCAB
としたい。どうすればいいか。
─答え─
問1
正解: A
解説: 前方のメソッドが後方のメソッドで上書きされるから。
問2
正解: AB
解説: `include B`により継承順位が`A -> B`となり、A#initializeにおけるsuperでB#initializeが呼ばれるから。継承順位はA.ancestorsで確認できます。
問3
正解: ABC
解説:includeの順位により継承順位が`A -> B -> C`となり、A#initializeにおけるsuperでB#initializeが呼ばれ、次いでB#initializeにおけるsuperでC#initializeが呼ばれるから。
問4
正解: ACB
解説: クラスAにBがincludeされたときに、B.includedメソッドが呼び出されてAにCがincludeされることとなり、継承順位は`A -> C -> B`となるから。
問5
正解:B.included内の`include`を`prepend`に書き換える。
解説: Module#prependはクラスAの前にモジュールCを差し込み、継承順位を`C -> A -> B`とします。
module C
def initialize
print :C
super
end
end
module B
def self.included(base)
base.send :prepend, C
end
def initialize
print :B
super
end
end
class A
include B
def initialize
print :A
super
end
end
A.new
頭の整理ついでに問題にしてみました。
blog comments powered by Disqus