Menu
Coddy logo textTech

Вызов super

Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 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

Три формы различаются тем, что они передают. 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 возвращает Ada (20), studies at MIT, построенное на основе super. 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