Menu
Coddy logo textTech

superの呼び出し

CoddyのRubyジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 24/57。

オーバーライドするメソッド内では、superによって同じメソッドのスーパークラス版を呼び出します。サブクラスは、結果を繰り返し処理する代わりに、その結果を基に処理を構築できます。

class Greeter
  def greet(name)
    "Hello, #{name}"
  end
end

class LoudGreeter < Greeter
  def greet(name)
    super.upcase + "!"
  end
end

puts LoudGreeter.new.greet("Ada")

出力:

HELLO, ADA!

最も一般的な用途は initialize です。サブクラスは追加の値を受け取り、共有する値を super(...) でスーパークラスに渡し、自身の値を保存します。

class Person
  attr_reader :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end

class Student < Person
  attr_reader :school

  def initialize(name, age, school)
    super(name, age)
    @school = school
  end
end

s = Student.new("Ada", 20, "MIT")
puts "#{s.name}, #{s.age}, #{s.school}"

出力:

Ada, 20, MIT

3つの形式は、渡す内容が異なります。裸のsuperは、現在のメソッドが受け取ったのと同じ引数を渡します。super()は何も渡しません。super(a, b)は、まさにそれらを渡します。

class Base
  def show(*args)
    "Base got #{args.inspect}"
  end
end

class Child < Base
  def show(a, b)
    [super, super(), super(b)].join(" | ")
  end
end

puts Child.new.show(1, 2)

出力:

Base got [1, 2] | Base got [] | Base got [2]

super はメソッド内のどこでも、あるいは条件の下でのみ実行できます。サブクラスの initialize が親クラスのものとは異なる引数を取る場合、裸の super は誤った引数を渡すため、これはよくある ArgumentError になります。

class Logger
  def log(message)
    puts "LOG #{message}"
  end
end

class QuietLogger < Logger
  def log(message)
    super unless message.start_with?("debug")
  end
end

logger = QuietLogger.new
logger.log("started")
logger.log("debug x=1")
logger.log("done")

出力:

LOG started
LOG done
challenge icon

チャレンジ

簡単

クラスを完成させてください。Person は name と age を格納し、その to_s は Ada (36) を返します。Student は学校を追加します。initialize は名前と年齢を super に渡し、その to_s は super から構成された Ada (20), studies at MIT を返します。Teacher も同じ方法で科目を追加し、Bo (45), teaches maths を返します。

提供されたコードは、person Ada 36、student Ada 20 MIT、または teacher Bo 45 maths の行を読み込み、各オブジェクトを出力します。

コードは person.rb、student.rb、teacher.rb に記述します。main.rb には提供された入出力コードが含まれており、編集できません。

自分で試してみよう

require_relative 'person'
require_relative 'student'
require_relative 'teacher'

# 提供された入出力コード: そのままにしておく
input = []
while (line = gets)
  input << line.chomp
end
input.each do |line|
  kind, name, age, extra = line.split
  person = case kind
           when "student" then Student.new(name, age.to_i, extra)
           when "teacher" then Teacher.new(name, age.to_i, extra)
           else Person.new(name, age.to_i)
           end
  puts person
end
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Rubyオンラインコンパイラ