initializeメソッドの動き
スーパークラスとサブクラスでinitializeが定義されていた場合、どのような動きが起こるか確認していきます。
class Parent
attr_accessor(:name)
def initialize(name)
@name = name
end
end
class Child < Parent
attr_accessor(:grade)
def initialize (grade)
@grade = grade
end
end
p Child.new("10") #=> @grade="10
p Parent.new("Aki") #=> @name="Aki"
サブクラスに引数を与え、呼び出したとき、スーパークラスを呼び出さず、サブクラスのinitializeメソッドが呼び出されているのがわかります。
これは、通常のメソッドを下位レベルから探していくのと同じ手順です。
サブクラスのinitializeにsuperを設定
initializeが重なっていた場合にスーパークラスのinitializeにsuperを設定することで、初期値を変更することで細かく制御することができる。
ただし、superの呼び出し方で反応が変わるので注意が必要です。
class Parent
attr_accessor(:name)
def initialize(name)
@name = name
end
end
class Child < Parent
attr_accessor(:grade)
def initialize (grade)
super("foo") #=> @name="foo"
super #=> @name="10"
super "foo" #=> @name="foo"
super() #=> ArgumentError
@grade = grade
end
end
p Child.new("10")
super("foo")
とsuper "foo"
では、初期値を設定しているため@name="foo"
という値が返ります。
super
のみで呼び出す場合は、初期値の呼び出しがないため、スーパークラスのinitializeメソッドが呼び出され、@name="10"
が設定されます。
super()
ではerrorが発生します。
構文としては間違っていませんが、使用する場面としてはオーバーライドされるメソッドに引数を渡さずにsuperを使用したい時に限ります。(この場合、"10"を引数として渡したくない)
この場合はsuperに()をつけて明示的に示す必要があります。ただし、スーパークラスのメソッドの引数は定義すると使えないようです。
class Parent
attr_accessor(:name)
def initialize()
@name = name
end
end
class Child < Parent
attr_accessor(:grade)
def initialize (grade)
super() #=> @name=nil
@grade = grade
end
end
p Child.new("10")
参考
- Effective Ruby
- https://techracho.bpsinc.jp/hachi8833/2018_06_20/57090