Пару недель назад я написал о наследовании в Ruby с примером, который помог мне разобраться в основной концепции. Теперь я хочу поговорить о том, как это реализовать, поскольку именно здесь проявляется первая настоящая морщина.
Когда вы пытаетесь передать код из родительского класса в дочерний класс, вам нужно знать только три инструмента, чтобы получить все необходимые функции:
- Неявное наследование метода
- Наследование переопределенного метода
- Наследование измененного метода
Неявное наследование
Это простейшая форма наследования, которую я рассмотрел в предыдущем посте. По сути, если у вас есть класс с именем A, который наследуется от класса с именем A, любой объект B сможет использовать все методы, доступные для A. Или, более конкретно, если у вас есть класс с именем Vehicles, который выглядит следующим образом:
И вы создаете класс Automobiles, наследующий от него:
Затем Ruby построит ваш класс Automobile, чтобы он выглядел так:
На самом деле вам не нужно писать весь этот код - только маркер наследования после вашего класса
< Vehicle
и он автоматически предоставит все функции Vehicle (примечание: он не перезапишет ваш файл Ruby новым кодом, но когда Ruby вызывает класс Automobile, он увидит именно это.
Переопределить наследование
На первый взгляд, это потрясающе мощный инструмент, который вам предоставляют классы Ruby. Но в какой-то момент может оказаться слишком мощным. Что, если в родительском классе есть метод, о котором дочерний элемент не должен знать или который дочерний класс должен обрабатывать иначе, чем родительский? Что, если, например, вы хотите, чтобы скорость на машине увеличилась на 10, а не на 5 по умолчанию в классе транспортных средств?
Чтобы справиться с этой возможностью, Ruby позволяет вам переопределить родительские методы в своих дочерних классах, просто переопределив метод локально:
В этом случае наследование позволит Ruby предоставить автомобилям методы initialize и slow_down, определенные в разделе Vehicles, но он пропустит speed_up, поскольку он уже определен. На бэкэнде Ruby видит этот набор методов для вашего класса:
Измененное наследование
Итак, скажем, вместо того, чтобы полностью переопределить то, что говорит родительский класс, вы хотите, чтобы ваш дочерний класс взял эту информацию и сделал с ней что-то немного другое. Именно здесь на помощь приходит измененное наследование. Это может быть труднее всего понять с синтаксической точки зрения, но на самом деле это просто переопределение наследования с помощью специального метода под названием super, который позволяет вам извлекать информацию из родительского класса.
Допустим, вы хотите установить ограничение скорости для автомобилей на уровне 65 миль в час, но не для транспортных средств в целом (потому что в транспортных средствах также должны быть разрешены и самолеты, которые должны двигаться быстрее). Вы можете просто сделать это с помощью переопределенного наследования, как в примере выше. Это будет примерно так:
Когда класс Automobile создает его метод speed_up, его собственный метод переопределяет одно транспортное средство, которое пытается его отправить, и автомобиль остается с ограничением скорости, которого нет у транспортного средства.
Это работает само по себе, но стоит отметить одну вещь: строки 18 и 19 в разделе "Автомобиль" в точности идентичны строкам 8 и 9 в разделе "Транспортное средство". И в этом есть смысл - я пытался написать автомобиль таким образом, чтобы он действовал точно так же, как автомобиль, когда скорость ниже 65, но делал что-то другое, когда она выше.
Чтобы позволить мне написать эти строки только один раз, Ruby представил метод super (), который проверяет метод в родительском классе с тем же именем, что и тот, в котором используется super, и вставляет этот исходный код в дочерний класс. метод. Чтобы полностью понять, что это означает, код, который я опубликовал, будет работать идентично этому коду, который использует super:
Опять же, сначала это может показаться странным, но все, что я делаю, это переопределяю метод, определенный Vehicle, а затем вызываю этот фрагмент кода в новом методе, который я написал.