Урок №159. Вызов и переопределение методов родительского класса

  Юрий Ворон  | 

    | 

  Обновлено 10 Сен 2018  | 

 880

Дочерние классы по умолчанию наследуют все методы родительского класса. В этом уроке мы рассмотрим, как это происходит, а также как можно изменить методы родительских классов в дочерних классах.

Вызов методов родительского класса

При вызове метода через объект дочернего класса, компилятор сначала смотрит, существует ли этот метод в дочернем классе. Если нет, то он начинает продвигаться по цепочке наследования вверх и проверяет, был ли этот метод определен в любом из родительских классов. Использоваться будет первое найденное определение. Например:

Результат:

I am a Parent!
I am a Parent!

При вызове child.identify(), компилятор смотрит, определен ли метод identify() в классе Child. Это не так. Поэтому компилятор переходит к классу Parent. В классе Parent есть определение метода identify(), поэтому компилятор использует именно это определение.



Переопределение методов родительского класса

Однако, если бы мы определили identify() в классе Child, то использовалось бы именно это определение. Это означает, что мы можем заставить родительские методы работать по-другому с нашими дочерними классами, просто переопределяя их в дочерних классах!

В примере выше было бы лучше, если бы child.identify() выводил бы «I am a Child!». Давайте изменим метод identify() в классе Child, так чтобы он возвращал правильный ответ.

Переопределение родительского метода в дочернем классе происходит как обычное определение метода:

Вот тот же код main(), что в примере выше, но уже с внесенными изменениями в класс Child:

Результат:

I am a Parent!
I am a Child!

Обратите внимание, когда мы переопределяем родительский метод в дочернем классе, то дочерний метод не наследует спецификатор доступа родительского метода с тем же именем. Используется тот спецификатор доступа, который указан в дочернем классе. Таким образом, метод, определенный как private в родительском классе, может быть переопределен как public в дочернем классе, или наоборот!

Расширение функционала родительских методов

Могут быть случаи, когда нам не нужно полностью заменять метод родительского класса, но нужно просто расширить его функционал. В примере выше, обратите внимание, что Child::identify() полностью перекрывает Parent::identify()! Возможно, это не то, что нам нужно. Мы можем вызвать метод родительского класса с тем же именем в методе дочернего класса (для повторного использования кода), а затем добавить дополнительно свой код.

Чтобы метод дочернего класса вызывал метод родительского класса с тем же именем нужно просто выполнить обычный вызов функции, но с добавлением имени родительского класса и оператора разрешения области видимости. В следующем примере мы выполним переопределение identify() в классе Child, вызывая сначала Parent::identify(), а затем добавляя уже свой код:

Вместе с:

Даёт результат:

I am a Parent!
I am a Parent!
I am a Child!

При выполнении child.identify() выполняется вызов Child::identify(). В Child::identify() мы сначала вызываем Parent::identify(), который выводит «I am a Parent!». Когда Parent::identify() завершает своё выполнение, Child::identify() продолжает своё выполнение и выводит «I am a Child!».

Всё просто. Зачем тогда нужно использовать оператор разрешения области видимости (::)? А затем, что, если бы мы определили Child::identify() следующим образом:

То вызов метода identify() без указания оператора разрешения области видимости привел бы к вызову identify() в текущем классе, т.е. к Child::identify(). Затем снова вызов Child::identify() и ура – у нас получился бесконечный цикл. Поэтому использование оператора разрешения области видимости является обязательным условием при изменении методов родительского класса.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (11 оценок, среднее: 4,91 из 5)
Загрузка...

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *