C# Наследование

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

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

Концепция наследования реализуетIs-a (IS-A)отношение. Например, млекопитающиеIs-a (IS-A)Animal, DogIs-a (IS-A)млекопитающие, следовательно, собакиIs-a (IS-A)Animal.

Базовые классы и производные классы

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

C# не поддерживает множественное наследование классов, но поддерживает множественное наследование интерфейсов; класс может реализовывать несколько интерфейсов.

В итоге:Класс может наследоваться от нескольких интерфейсов, но может наследоваться только от одного класса.

Синтаксис создания производного класса в C# выглядит так:

<Модификаторы доступа> class <базовый класс>
{
 ...
}
class <производный класс> : <базовый класс>
{
 ...
}

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

Производный класс может вызывать конструкторы и методы базового класса через ключевое слово `base`.

Пример

class BaseClass
{
    public void SomeMethod()
    {
        // Реализация метода
    }
}

class DerivedClass : BaseClass
{
    public void AnotherMethod()
    {
        // Обращение к методу базового класса
        base.SomeMethod();
       
        // Реализация метода
    }
}

Предположим, есть базовый класс Shape, а его производный класс — Rectangle:

Пример

using System;
namespace InheritanceApplication
{
   class Shape
   {
      public void setWidth(int w)
      {
         width = w;
      }
      public void setHeight(int h)
      {
         height = h;
      }
      protected int width;
      protected int height;
   }

   // Производный класс
   class Rectangle: Shape
   {
      public int getArea()
      {
         return (width * height);
      }
   }
   
   class RectangleTester
   {
      static void Main(string[] args)
      {
         Rectangle Rect = new Rectangle();

         Rect.setWidth(5);
         Rect.setHeight(7);

         // вывести площадь объекта
         Console.WriteLine("Общая площадь: {0}", Rect.getArea());
         Console.ReadKey();
      }
   }
}

Когда приведённый выше код компилируется и выполняется, он выдаёт следующий результат:

总面积: 35

Инициализация базового класса

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

Следующая программа демонстрирует это:

Пример

using System;
namespace RectangleApplication
{
   class Rectangle
   {
      // Переменные-члены
      protected double length;
      protected double width;
      public Rectangle(double l, double w)
      {
         length = l;
         width = w;
      }
      public double GetArea()
      {
         return length * width;
      }
      public void Display()
      {
         Console.WriteLine("Длина: {0}", length);
         Console.WriteLine("Ширина: {0}", width);
         Console.WriteLine("Площадь: {0}", GetArea());
      }
   }//конец класса Rectangle  
   class Tabletop : Rectangle
   {
      private double cost;
      public Tabletop(double l, double w) : base(l, w)
      { }
      public double GetCost()
      {
         double cost;
         cost = GetArea() * 70;
         return cost;
      }
      public void Display()
      {
         base.Display();
         Console.WriteLine("Cost: {0}", GetCost());
      }
   }
   class ExecuteRectangle
   {
      static void Main(string[] args)
      {
         Tabletop t = new Tabletop(4.5, 7.5);
         t.Отобразить();
         Console.ReadLine();
      }
   }
}

Когда приведённый выше код компилируется и выполняется, он выдаёт следующий результат:

长度: 4.5
宽度: 7.5
面积: 33.75
成本: 2362.5

Наследование интерфейсов

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

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

Пример

interface IBaseInterface
{
    void Method1();
}

interface IDerivedInterface : IBaseInterface
{
    void Method2();
}

Наследование интерфейса можно реализовать следующим образом:

Пример

using System;

// определить базовый интерфейс
interface IBaseInterface
{
    void Method1();
}

// Определить производный интерфейс, который наследует базовый интерфейс
interface IDerivedInterface : IBaseInterface
{
    void Method2();
}

// Класс, реализующий производный интерфейс
class MyClass : IDerivedInterface
{
    public void Method1()
    {
        Console.WriteLine("Реализация Method1");
    }

    public void Method2()
    {
        Console.WriteLine("Реализация Method2");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Создать экземпляр класса MyClass
        MyClass obj = new MyClass();

        // Вызвать метод, унаследованный от базового интерфейса
        obj.Method1();

        // Вызов метода, недавно добавленного производным интерфейсом
        obj.Method2();
    }
}

В приведённом выше примере класс MyClass реализует интерфейс IDerivedInterface, поэтому он должен предоставить все методы, определённые в IDerivedInterface, включая метод Method1(), унаследованный от IBaseInterface. В методе Main мы создаём экземпляр obj класса MyClass и вызываем его методы.

Результат вывода:

Method1 implementation
Method2 implementation

Множественное наследование в C#

Множественное наследование — это возможность класса наследовать поведение и характеристики более чем от одного родительского класса одновременно. В отличие от одиночного наследования, одиночное наследование означает, что класс может наследовать только от одного родительского класса.

C# не поддерживает множественное наследованиеОднако можно использовать интерфейсы для реализации множественного наследования. Следующая программа демонстрирует это:

Пример

using System;
namespace InheritanceApplication
{
   class Shape
   {
      public void setWidth(int w)
      {
         width = w;
      }
      public void setHeight(int h)
      {
         height = h;
      }
      protected int width;
      protected int height;
   }

   // Базовый класс PaintCost
   public interface PaintCost
   {
      int getCost(int area);

   }
   // Производный класс
   class Rectangle : Shape, PaintCost
   {
      public int getArea()
      {
         return (width * height);
      }
      public int getCost(int area)
      {
         return area * 70;
      }
   }
   class RectangleTester
   {
      static void Main(string[] args)
      {
         Rectangle Rect = new Rectangle();
         int area;
         Rect.setWidth(5);
         Rect.setHeight(7);
         area = Rect.getArea();
         // вывести площадь объекта
         Console.WriteLine("Общая площадь: {0}", Rect.getArea());
         Console.WriteLine("Общая стоимость краски: ${0}" , Rect.getCost(area));
         Console.ReadKey();
      }
   }
}

Когда приведённый выше код компилируется и выполняется, он выдаёт следующий результат:

总面积: 35
油漆总成本: $2450
Другие расширения