Классы и объекты C#: наследование

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

Простой пример наследования в C#

Чтобы понять суть наследования в C# вернемся к нашему классу Building, который описывает некое здание. Этот класс описывает размеры здания (длину, ширину и высоту) и даже имеет метод расчёта объема и несколько свойств. Мы с этим классом можем работать как угодно в рамках его функциональности. А теперь представим, что нам потребовалось добавить в программу работу не только с некими абстрактными зданиями, а конкретизировать их назначение и свойства, например, нам необходим класс, который будет описывать жилой дом. В этом случае мы можем пойти двумя путями:

  1. Создать новый класс, описать в нем те же свойства, что и у класса Building и добавить интересующие нас свойства.  Несмотря на то, что такой подход вполне сработает, делать так категорически не стоит. О том, почему так не стоит делать мы узнаем ниже, когда ощутим все преимущества наследования в C#.
  2. Наследовать новый класс от класса Building и дописать необходимые свойства и методы.

Итак, назовем наш новый класс House и наследуем его от класса Building. О том, как в Visual Studio C# создать заготовку класса рассказано здесь. Вот как может выглядеть наш новый класс:

internal class House: Building
{
    private int windowCount;
    public int WindowCount
    {
        get => windowCount;
        set => windowCount = value >= 0 ? value : throw new Exception("Количество окон не может быть меньше нуля");
    }
}

В абстрактном виде этот код можно прочитать следующим образом:

класс House унаследован от класса Building
начало описания
   Свойство "Количество окон"
конец описания

При этом, обратите внимание на то, что мы не повторялись в описании нового класса и не переносили в него свойства и методы класса Building — они наследовались в новом классе и мы их можем спокойно использовать, например (про упрощенную инициализацию объектов в C# смотри здесь),

using FirstClass;

House house = new House
{
    Name ="Жилой дом №1",
    Height = 5,
    Length = 15,
    Width = 20,
    WindowCount = 5
};
Console.WriteLine($"Объем дома {house.Volume}");
Console.WriteLine($"Количество окон {house.WindowCount}");
Console.WriteLine($"{house}");

Как видите, мы использовали все возможности класса Building, а также воспользовались новым свойством WindowCount, используя механизмы наследования в C#. В этом-то и кроется вся мощь наследования — мы не повторяемся в коде и наделяем наследников только теми свойствами и методами, которые характерны именно для них, а все общие свойства наследуются автоматически от предков. Вот почему выше я написал, что первый путь создания нового класса в корне не верен и контрпродуктивен во всех смыслах.

Особенности наследования в C#

Как и любой язык программирования, C# обладает своими возможностями и особенностями, которые нам следует помнить и знать. Что касается наследования, то в C# следует помнить, что наследование классов может осуществляться последовательно. Например,

internal class MultiStoreyBuilding: House
{
    public int FloorCount { get; set; }
}

здесь для упрощения кода использовано автосвойство FloorCount. Теперь цепочка наследования выглядит следующим образом: Building -> House -> MultiStoreyBuilding и класс MultiStoreyBuilding обладает всеми свойствами как для класса Building, так и для House:

MultiStoreyBuilding house = new MultiStoreyBuilding
{
    Name ="Жилой дом №1",
    Height = 5,
    Length = 15,
    Width = 20,
    WindowCount = 5,
    FloorCount = 5,
};

При этом в C# мы не можем использовать множественное наследование от нескольких классов. Например, следующий код не скомпилируется:

internal class MultiStoreyBuilding: House, Building
{
    public int FloorCount { get; set; }
}

и Visual Studio выдаст следующую ошибку:

Для того, чтобы создать класс-наследник нескольких базовых классов нам необходимо идти последовательно, расширяя функциональность нашей программы.  При этом, никто не запрещает нам в C# создавать несколько различных наследников от одного базового класса. Например, мы бы могли унаследовать от класса Building сразу несколько классов — частный дом, многоквартирный дом, сарай и так далее.

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

Итого

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

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии