Как организовать объектно-ориентированный код с помощью наследования
Технологии с объяснениями

Как организовать объектно-ориентированный код с помощью наследования

Правильное освоение объектно-ориентированного программирования означает, что вам необходимо знать о наследовании и о том, как оно может упростить кодирование и уменьшить количество ошибок

В объектно-ориентированном программировании принято повторно использовать код. Классы существуют для того, чтобы вы могли создавать объекты без необходимости писать одни и те же переменные и функции снова и снова

Но как насчет самих классов? Иногда классы также очень похожи. Например, у дерева есть ветви, корни и ствол. Это относится к вязам, дубам и соснам Пондероза

Если бы вы добавляли дерево в игру, вы могли бы создать части дерева для десятков деревьев. Но проще было бы создать один класс дерева, чтобы все остальные деревья наследовали его свойства

Почему наследование важно?

В объектно-ориентированном программировании есть концепция, называемая ‘keep it DRY’. DRY расшифровывается как ‘Не повторяй себя’. Если вы копируете и вставляете много кода, вы допускаете много ошибок

Допустим, вы пишете код для новой игры Tamagotchi. Первым виртуальным питомцем будет белый медведь. Поэтому вы создаете класс PolarBear в JavaScript/TypeScript

class PolarBear { private _weight: number = 990; constructor(weight: number = 0) { this._weight = weight } makeNoise() { console.log('made a roar'); } eat() { console.log('eats whatever it wants'); } sleep() { console.log('got a good night's sleep'); } roam() { console.log('wandered about aimlessly'); }}

Затем ваш босс говорит вам, что высшее руководство совершило огромный прорыв. Они поняли, что сейчас не 90-е годы, и в тамагочи можно вместить более 5К памяти. И теперь им нужны все медведи

Вы засучиваете рукава и возвращаетесь к работе, создавая копии класса медведей. Затем ваш босс снова стучится к вам в дверь. Оказывается, они хотят сделать игру более образовательной. Теперь вы должны добавить информацию о происхождении каждого питомца

Вы больше не дублируете код. Теперь вы меняете сотни строк кода для всех восьми видов медведей. Так происходят ошибки, и появляются баги

Пока вы работаете, к вам снова подходит ваш босс. Теперь высшее руководство хочет, чтобы в игре были и все грызуны. И еще жирафа

Вы знаете, что когда вы закончите, они захотят обезьян или что-то еще. Должен быть лучший способ

Вместо того чтобы создавать тамогатчи нового поколения, вы всегда можете поиграть с уже существующими

Наследственность в помощь

Для того чтобы приручить свой виртуальный зверинец, вам понадобится организация. Наследование помогает упорядочить классы, добавляя к ним родительские и дочерние отношения

Черные медведи, гризли и медведи-ленивцы – все они медведи. Медведи, грызуны и обезьяны – это все животные. И именно так мы будем строить наше семейное дерево

Вот как выглядит часть кода:

class Animal { private _weight: number; private _origin: string; constructor(weight: number = 0, origin: string = '') { this._weight = weight; this._origin = origin; } makeNoise(noise: string = '') { console.log('made a noise that sounded like: ' + noise); } eat(food: string = '') { console.log('eats ' + food); } sleep() { console.log('got a good night's sleep'); } roam() { console.log('wandered about aimlessly'); }}class Bear extends Animal { constructor(weight: number, origin: string) { super(weight, origin); } makeNoise(noise: string = 'roar') { super.makeNoise(noise); } eat(food: string = 'whatever it wants') { super.eat(food); }}class GrizzlyBear extends Bear { constructor(weight: number = 600, origin: string = 'North America') { super(weight, origin); }}class Panda extends Bear { constructor(weight: number = 230, origin: string = 'China') { super(weight, origin); } makeNoise() { super.makeNoise('squeek'); } eat() { super.eat('shoots and leaves'); }}

Вы можете поиграть с кодом в песочнице TypeScript

Это был большой пример, но код достаточно прост, и все классы являются потомками класса Animal. Вы можете видеть, что Bear расширяет Animal. А GrizzlyBear и Panda расширяют класс Bear. Класс Bear создает функции по умолчанию sound и eat. Класс GrizzlyBear использует эти функции по умолчанию, а класс Panda – нет

Другими словами, класс GrizzlyBear не переопределяет функции Bear. Поскольку GrizzlyBear расширяет Bear , он будет использовать функции, определенные Bear , автоматически. Но поскольку Panda переопределяет функции makeNoise и eat , он будет использовать их вместо этого

Поиск взаимосвязей с помощью техники ‘is-a, has-a’

Чтобы выяснить, действительно ли класс должен расширять другой класс, вы можете спросить себя, есть ли между ними отношения ‘is-a’ или ‘has-a’

  • Лемур ‘является’ обезьяной.
  • Кенгуру ‘является’ сумчатым.
  • Нога кролика – это не кролик. Кролик ‘имеет’ лапку.

Этот пример немного упрощен, но при работе с реальными классами он может быть очень полезен

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

Готовы применить полученные знания?

  • Посетите песочницу и заполните остальные классы животных из примера выше.
  • Добавьте класс Обезьяна.
  • Добавьте класс ProboscisMonkey , который расширяет ваш класс обезьяны.

Наследование – это больше, чем просто хорошо организованный код. Это основная часть объектно-ориентированного программирования. Наследование помогает упростить взаимодействие между объектами. Кроме того, оно позволяет использовать более продвинутый объектно-ориентированный дизайн, например, полиморфизм. Подробнее о наследовании можно узнать из документации по TypeScript

Об авторе

Алексей Белоусов

Привет, меня зовут Филипп. Я фрилансер энтузиаст . В свободное время занимаюсь переводом статей и пишу о потребительских технологиях для широкого круга изданий , не переставая питать большую страсть ко всему мобильному =)

Комментировать

Оставить комментарий

ВАМ БУДЕТ ИНТЕРЕСНО