Menu
Coddy logo textTech

Переопределение методов

Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 23 из 57.

Подкласс может переопределить метод, определив метод с тем же именем. Ruby сначала ищет метод в собственном классе объекта и только затем в суперклассе, поэтому версия подкласса имеет приоритет:

class Animal
  def speak
    "..."
  end
end

class Dog < Animal
  def speak
    "Woof"
  end
end

class Fish < Animal
end

puts Dog.new.speak
puts Fish.new.speak

Вывод:

Woof
...

Метод суперкласса, вызывающий другой метод, использует переопределённую версию для объектов подкласса. Общий метод записывается один раз, а каждый подкласс изменяет только отличающуюся часть:

class Animal
  def initialize(name)
    @name = name
  end

  def introduce
    "#{@name} says #{speak}"
  end

  def speak
    "..."
  end
end

class Cat < Animal
  def speak
    "Meow"
  end
end

puts Cat.new("Tom").introduce
puts Animal.new("Thing").introduce

Результат:

Tom says Meow
Thing says ...

Переопределение to_s в подклассе изменяет способ вывода только этого подкласса. Методы, которые он не переопределяет, по-прежнему наследуются от суперкласса:

class Item
  def initialize(name, price)
    @name = name
    @price = price
  end

  def to_s
    format("%s %.2f", @name, @price)
  end
end

class SaleItem < Item
  def to_s
    format("%s %.2f (sale)", @name, @price * 0.8)
  end
end

puts Item.new("Lamp", 20)
puts SaleItem.new("Lamp", 20)

Вывод:

Lamp 20.00
Lamp 16.00 (sale)

Порядок, в котором Ruby выполняет поиск, задаётся предками класса: сначала сам класс, затем его суперкласс и так далее вплоть до Object. Первый класс в этом списке, который определяет метод, предоставляет его:

class Animal
  def speak
    "..."
  end
end

class Dog < Animal
  def speak
    "Woof"
  end
end

class Puppy < Dog
end

puts Puppy.new.speak
p Puppy.ancestors.take(3)

Вывод:

Woof
[Puppy, Dog, Animal]
challenge icon

Задание

Легко

Завершите классы для расчёта заработной платы. Employee хранит name и имеет pay(hours), который возвращает hours * 20, а также payslip(hours), который с использованием pay возвращает Ada: 800. Manager переопределяет pay, возвращая фиксированное значение 1500 независимо от количества часов. Intern переопределяет pay, возвращая hours * 12, но не более 300. payslip определён только в Employee.

Предоставленный код считывает строки employee Ada 40, manager Bo 50 или intern Cy 20, создаёт соответствующий объект и выводит его расчётный листок, а затем выводит общую выплату.

Ваш код должен находиться в файлах employee.rb, manager.rb и intern.rb. В main.rb находится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

require_relative 'employee'
require_relative 'manager'
require_relative 'intern'

# Предоставленный код ввода/вывода: оставьте его как есть
input = []
while (line = gets)
  input << line.chomp
end
kinds = { "employee" => Employee, "manager" => Manager, "intern" => Intern }
total = 0
input.each do |line|
  kind, name, hours = line.split
  worker = kinds[kind].new(name)
  puts worker.payslip(hours.to_i)
  total += worker.pay(hours.to_i)
end
puts "total: #{total}"
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Ruby