Наследование в программировании это: Наследование в программировании: определение, виды, описание и отличия

Содержание

Наследование в программировании: определение, виды, описание и отличия

Наследование классов в программировании свойственно объектно-ориентированным языкам, например С. Наследование входит в основные принципы ООП и стоит рядом с такими принципами, как:

  • абстракция,

  • инкапсуляция,

  • полиморфизм.

Абстракция — это процесс придания объекту уникальных характеристик, которые выделяют его среди других объектов, подчеркивая его концепцию и основные свойства.

Инкапсуляция — это подход в ООП, который позволяет программисту взаимодействовать с программным компонентом, не задумываясь о том, что у него внутри, а также наладить этому компоненту защиту при помощи публичных методов.

Полиморфизм — это способность объектов с одинаковой спецификой по-разному реализовываться.

Подробнее на каждом принципе мы остановимся в следующих статьях. А сегодня расскажем, что такое наследование в ООП.

Наследование классов в ООП (объектно-ориентированном программировании) 

Наследование в программировании — это возможность описать новый класс объекта на основе уже существующего. При таком подходе наследующий класс «перенимает» специфику родительского класса и использует ее по собственному назначению.

Другими словами, наследование помогает повторно использовать уже написанный код для определенного класса. Использование наследования образует иерархию классов, где присутствуют:

  • родительские или базовые классы — это классы, от которых заимствовали характеристики и свойства;

  • потомственные или наследующие классы — это классы, которые получились на основе характеристик родительских классов.

Наследование может быть 2-х видов:

  • простое,

  • множественное.

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

Простое наследование еще называется одиночным — это наследование, при котором создается «родство» между двумя классами. То есть один класс-потомок перенимает характеристики от одного родительского класса.

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

Множественное наследование классов в программировании

Множественное наследование классов подразумевает ситуацию, когда один потомственный класс принимает характеристики от нескольких родительских классов. Такой подход помогает реализовывать очень гибкие и настраиваемые классы-потомки.

Его поддерживают не все ОО-языки. Например, множественное наследование поддерживают C, C++, Python, Eiffel, UML, но не поддерживают Java и C#. Некоторые языки отказались от множественного наследования, потому что оно является источником потенциальных ошибок из-за присутствия одинаковых имен у классов. Поэтому в таких языках было решено уйти от множественного наследования и заменить его интерфейсами.

Интерфейс — это подход в программировании, при котором определяются отношения между объектами, связанными похожими характеристиками. Такой подход довольно популярен в объектно-ориентированном программировании, так как исключает многие ошибки, возникающие в других подходах.

Наследование в программировании: реализация в языках

Давайте посмотрим, как реализуется наследование в некоторых языках программирования.

Наследование классов в С/С++ реализуется по следующему шаблону:

class Q {}; // Родительский класс

 

class W : public Q {}; // спецификатор Public

class E : protected Q {}; // спецификатор Protected

class R : private Q {}; // спецификатор Private

 

Как видно, в С/С++ наследование может быть организовано тремя спецификаторами. Данные спецификаторы объявляются в родительском и потомственном классе. Разный спецификатор — разные отношения между этими классами. Данной теме мы посвятим отдельную статью.

Множественное наследование на Python происходит по следующему шаблону:

class FirstParent(object):   # первый родительский класс

    def m1(self): pass

class SecondParent(object):   # второй родительский класс

    def m1(self): pass

class Inheritor(FirstParent, SecondParent):   # Потомственный класс с двумя родительскими

   

В PHP реализация наследования происходит по следующему шаблону:

 

class Inheritor extends Parent {

}

Важная особенность в PHP — родительский класс объявляется после потомственного класса, при этом обязательно использовать перед именем родительского класса ключевое слово «extends».

Заключение

Наследование классов в программировании — это возможность повторно использовать уже написанный код для какого-либо класса. А это существенно экономит время на разработку и отладку программы.

Наследование классов — это процесс, связанный с объектно-ориентированным программированием, однако в разных ОО-языках он реализован по-разному. Например, множественное наследование поддерживают не все объектно-ориентированные языки.

Наследование в объектно-ориентированном программировании. Курс «ООП на Kotlin»

Наследование – это одно из ключевых составляющих объектно-ориентированного программирования. В первую очередь оно позволяет

  • общую функциональность нескольких классов выносить в один общий суперкласс,

  • совместно обрабатывать объекты, созданные от разных, но родственных, классов.

Вспомним наш класс:

class NumInc(n: Int, gap: Int) {
    var number = n
    var step = gap
 
    fun inc() {
        number += step
    }
    fun dec() {
        number -= step
    }
}

Допустим, в программе должны быть объекты, поле number которых можно только увеличивать и уменьшать на величину шага.

Также в программе нужны объекты, у которых number может изменяться не только добавлением/вычитанием шага, но также умножением на шаг. Конечно, мы можем написать еще один класс:

class NumMult(n: Int, gap: Int) {
    var number = n
    var step = gap
 
    fun inc() {number += step}
    fun dec() {number -= step}    
    fun mult() {number *= step}
}

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

Чтобы класс мог быть родительским перед его объявлением должно стоять ключевое слово open.

open class NumInc(n: Int, gap: Int) {
...

В свою очередь класс-наследник должен в своем заголовке иметь запись о родительском классе. В нашем случае определение класса NumMult будет выглядеть так:

class NumMult(num: Int, coef: Int): NumInc(num, coef) {
 
    fun mult() {number *= step}
 
}

В заголовке после параметров первичного конструктора (если он есть) ставится двоеточие, после которого идет имя родительского класса. Поскольку конструктор родительского класса предусматривает два параметра, мы должны их туда передать.

После этого объекты NumMult будут обладать теми же свойствами и методами, что и объекты NumInc. У них тоже появятся свойства number и step, методы inc() и dec(). Однако помимо этого у них есть метод mult(), которого нет у объектов родительского класса.

Наследование может быть сложнее. Дочерний класс может стать родительским по отношению к другому дочернему. Для этого перед его объявлением также должно стоять слово open.

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

Давайте усложним наш пример, введя в дочерний класс третье свойство.

class NumMult(num: Int, gap: Int, coef: Int): NumInc(num, gap) {
    var coefficient = coef
 
    fun mult() {number *= coefficient}
}

Теперь дочерний класс обладает не только дополнительным методом, но и дополнительным полем. Конструктору родительского мы по-прежнему передаем два аргумента. Больше он и не принимает.

При создании объекта от класса NumMult надо передавать три аргумента:

val b = NumMult(1, 3, 2)

Первые два будут присвоены полям number и step и использоваться в функциях inc() и dec(). Третий будет присвоен свойству coefficient и использоваться только в методе mult().

Теперь представим, что класс NumMult имеет два конструктора, а у NumInc он по прежнему один. В это случае вторичный конструктор NumMult должен делегировать к первичному своего же класса, а уже тот будет обращаться к конструктору родительского класса.

class NumMult(num: Int, gap: Int, coef: Int): NumInc(num, gap) {
    var coefficient = coef
 
    constructor() : this(0, 1, 2)
 
    fun mult() {number *= coefficient}
}

Пример создания объекта через вторичный конструктор:

val c = NumMult()

Если у дочернего класса есть первичный конструктор, то все вторичные должны делегировать к нему. И только через него – к конструктору родительского класса. Однако если первичного конструктора нет, вторичные должны напрямую вызывать конструкторы родительского класса через ключевое слово super. Пример с двумя конструкторами как в основном, так и в дочернем классе при том, что в дочернем нет первичного:

open class NumInc(n: Int, gap: Int) {
    var number = n
    var step = gap
 
    constructor(): this(0, 1)
 
    fun inc() {number += step}
    fun dec() {number -= step}
}
class NumMult: NumInc {
    var coefficient = 2
 
    constructor(num: Int, gap: Int, coef: Int): 
        super(num, gap) {
        coefficient = coef
    }
 
    constructor(): super()
 
    fun mult() {number *= coefficient}
}

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

Рассмотрим другое преимущество наследования в ООП. В Kotlin мы можем присвоить переменной более общего типа объект дочернего типа, а не только своего собственного.

val a: NumInc = NumInc(2, 1)
val b: NumInc = NumMult(1, 3, 2)

Однако, поскольку переменная b имеет тип NumInc через нее нельзя получить доступ к свойствам и методам, которых нет в NumInc. Объект NumMult приводится к типу NumInc с потерей своих дополнительных свойств и методов.

С другой стороны, как мы узнаем из следующего урока, дочерние классы не всегда и не только отличаются от родительских расширением их возможностей, часто лишь переопределением. У дочернего класса могут быть почти такие же методы, как у родительского, но их программный код будет несколько иным.

Таким образом, объекты разных дочерних классов одного родительского, или дочернего и родительского, могут обладать одними и теми же методами. Это позволяет производить групповую обработку таких разноклассовых объектов. Например, мы можем создать список объектов NumInc и NumMult, дальше в цикле перебрать список, вызывая один и тот же метод для всех объектов.

fun main() {
    val a: List<NumInc> = listOf(
        NumMult(),NumMult(3,4,3),
        NumInc(10, 3), NumInc(5, 1))
 
    for(i in a) {
        i.inc()
        println(i.number)
    }
}

Результат выполнения программы:

1
7
13
6

Практическая работа:

Переделайте последний пример классов из урока так, чтобы родительский класс содержал только один конструктор, а дочерний – два.

PDF-версия курса с ответами к практическим работам


Наследование и полиморфизм — Основы программирования

Дэйв Брауншвейг

Обзор

В объектно-ориентированном программировании наследование — это механизм базирования объекта или класса на другом объекте (прототипное наследование) или классе (наследование на основе классов) с сохранением аналогичной реализации. В большинстве объектно-ориентированных языков, основанных на классах, объект, созданный посредством наследования («дочерний объект»), приобретает все свойства и поведение родительского объекта (за исключением конструкторов, деструкторов, перегруженных операторов и дружественных функций базового класса). Наследование позволяет программистам создавать классы, основанные на существующих классах, задавать новую реализацию, сохраняя при этом то же поведение (реализуя интерфейс), повторно использовать код и независимо расширять исходное программное обеспечение с помощью общедоступных классов и интерфейсов. [1]

Обсуждение

Наследование  – это способ упорядочивания объектов в иерархии от наиболее общего к наиболее конкретному. Объект, который наследует от другого объекта, считается подтипом этого объекта. Пример может включать Instructor и Student, каждый из которых наследуется от Person. Когда мы можем описать связь между двумя объектами, используя фразу is-a , эта связь является наследованием.

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

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

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

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

Ключевые термины

наследство
Объект или класс, основанный на другом объекте или классе, использующий ту же реализацию или определяющий новую реализацию для сохранения того же поведения. [2]
полиморфизм
Предоставление единого интерфейса для сущностей разных типов. [3]

Каталожные номера

  • Прочитайте документы: объектно-ориентированное программирование в Python
  • Викиверситет: Компьютерное программирование

  1. Википедия: наследование (объектно-ориентированное программирование) ↵
  2. Википедия: наследование (объектно-ориентированное программирование) ↵
  3. Wikipedia: Polymorphism (Computing Science) ↵
007. Что в

00. слово, состоящее из слова

«Наследовать» , что означает «Производить» . Итак, наследование определяется как тенденция одного класса получать свойства и характеристики от других классов. Он предоставляет дополнительные функциональные возможности для извлечения функций из базового класса и значительного включения их в другие производные классы.

В компьютерном программировании наследование является важной концепцией парадигмы объектно-ориентированного программирования (ООП). Он предоставляет механизм для установления отношений и построения иерархий классов в составе объектов. Наследование означает использование предварительно написанного или созданного ранее кода. И нужно помнить одну вещь: мы просто используем код, а не обновляем или изменяем его. Функции и методы, определенные в одном классе, могут использоваться для управления другими элементами данных этого класса.

Понимание наследования

Чтобы понять наследование, нам нужно сосредоточиться на двух типах классов: подклассе и суперклассе .

Подкласс , , также известный как производный класс, это класс, который наследует свойство, а суперкласс также известен как базовый класс; это класс, от которого наследуются свойства. В некоторых случаях подкласс называется дочерним классом, а суперкласс известен как родительский класс. Итак, до сих пор очевидно, что подкласс, то есть дочерний класс, наследует свойства суперкласса, то есть родительского класса.

Как наследование делает работу такой легкой?

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

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

Типы наследования:
  1. Одиночное наследование: Один производный класс наследуется от одного базового класса.
  2. Множественное наследование: Один производный класс наследуется от многих базовых классов.
  3. Многоуровневое наследование: Один производный класс наследуется от других производных классов.
  4. Иерархальное наследование: Более одного производного класса наследуются от одного базового класса.
  5. Наследование гибридов: Сочетание более чем одного типа наследования.

Что можно сделать с наследством?

Если команда работает над большой программой или фрагментом кода, наследование действует как благословение. Нам не нужно писать код повторно; если есть иерархия в классах или классах, которые зависят друг от друга, мы можем использовать код наследования от базового класса к дочернему классу. Это предотвратит повторное написание одного и того же кода. Наследование также играет важную роль в динамическом программировании. Один код можно использовать во многих областях, и, следовательно, сложность может быть уменьшена. Если кто-то внесет изменения в один подкласс, это не повлияет на суперкласс или другие классы.

Преимущества наследования

Ниже перечислены некоторые плюсы наследования:

  1. Частое использование кода, написанного один раз, т. е. повторное использование кода.
  2. Один суперкласс может использоваться для количества подклассов в иерархии.
  3. Никаких изменений во всех базовых классах; просто делайте изменения только в родительском классе.
  4. Наследование используется для создания более доминирующих объектов.
  5. Наследование позволяет избежать дублирования и избыточности данных.
  6. Наследование используется, чтобы избежать пространственной и временной сложности.

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

Наследование важно в программировании из-за возможности повторного использования кода. Мы можем избежать дублирования данных и избыточности в нашей программе. Возьмем пример: если вы живете с родителями, то отец будет одним базовым классом, а вы (как ребенок) будете производным классом. Таким образом, мы можем наследовать многие вещи, такие как фамилия, адресная строка, город и штат от родительского класса. Кроме того, если мы хотим обновить адрес или что-то еще, мы просто изменим адрес базового класса, и все производные классы унаследуют свойство этого базового класса.

Почему мы должны использовать наследование?

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

Зачем нам наследство?

  1. Чтобы повторно использовать код, напишите код и применяйте его дальше, где это необходимо.
  2. Во избежание дублирования и избыточности данных в программе.
  3. Чтобы уменьшить пространственную и временную сложность.
  4. Легче в парадигме иерархического программирования.
  5. Переменные с одним и тем же именем могут использоваться несколько раз в области действия кода.
  6. Для создания доминирующих объектов данных и функций.

Кто является подходящей аудиторией для изучения технологий наследования?

  1. Студенты факультета компьютерных наук.
  2. Студенты, изучающие программирование.
  3. Программист среднего уровня.
  4. выпускников информационных технологий.
  5. Выпускники факультета электроники.
  6. Технический специалист, который занимается или хочет работать над иерархическим программированием.

Как эта технология поможет вам в карьерном росте?

Судя по обсуждению, технология наследования является важной частью объектно-ориентированного программирования, поэтому любой, кто хочет улучшить объектно-ориентированное программирование, должен иметь опыт работы с технологией наследования.

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

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

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