Абстрактные классы, методы и свойства

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

Абстрактный класс

Абстрактный класс  объявляется с ключевым словом abstract. Такой класс имеет свои правила:
1)  нельзя создавать экземпляры (объекты) абстрактного класса;
2) абстрактный класс может содержать как абстрактные методы/свойства, так и обычные;
3) в классе-наследнике должны быть реализованы все абстрактные методы и свойства, объявленные в базовом классе.

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

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

Абстрактные методы

Абстрактный метод – это метод, который не имеет своей реализации в базовом классе, но он должен быть реализован в классе-наследнике. Абстрактный метод может быть объявлен только в абстрактном классе.

Объявление абстрактного метода происходит при помощи ключевого слова abstract, и при этом фигурные скобки опускаются, точка с запятой ставится после заголовка метода:

[модификатор доступа] abstract [тип] [имя метода] ([аргументы]);

Реализация абстрактного метода в классе-наследнике происходит так же, как и переопределение метода, при помощи ключевого слова override:

[модификатор доступа] override [тип] [имя метода] ([аргументы])
{
  // реализация метода
}

Абстрактные свойства

Создание абстрактных свойств не сильно отличается от методов:

protected [тип] [поле, которым управляет свойство];
[модификатор доступа] abstract [тип] [имя свойства] { get; set; }

Реализация в классе-наследнике:

[модификатор доступа] override [тип] [имя свойства]
{
  get { тело аксессора get }
  set { тело аксессора set }
}

Пример «Правильный многоугольник»

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

abstract class Figure
{
   public double Length { get; set; }
   protected double Area;
   protected double Perimeter;
   public Figure(double len)
   {
      this.Length = len;
      Area=area();
      Perimeter=perimeter();
   }
   public void InfoFigure(string s)
   {
      Console.WriteLine(s + ": площадь = {0:###.###}, периметр = {1:###.###}", Area, Perimeter);
   }
   public abstract double area();
   public abstract double perimeter();
} 

где Length, Area, Perimeter – длина стороны, площадь и периметр многоугольника;
Figure( ) и InfoFigure( )– конструктор класса и обычный (не абстрактный) метод класса;
area( ) и perimeter( ) – абстрактные методы класса, в конструкторе они используются для нахождения полей класса Area и Perimeter.

Наследуем от абстрактного класса Figure класс Square («Квадрат»):

class Square : Figure
{
   public Square(double len) : base(len) {  }
   public override double area()
   {
      Area = Length * Length;
      return Area;
   }
   public override double perimeter()
   {
      Perimeter = 4 * Length;
      return Perimeter;
   }
}

В этом классе производится перегрузка конструктора Square( ), наследуемого от конструктора базового (base) класса Figure( ) – дополнительно вызываются методы area( ) и perimeter( ), которые конкретизируются далее.

Аналогично наследуем от абстрактного класса Figure класс Triangle («Треугольник»):

class Triangle : Figure
{
   public Triangle(double len) : base(len) {   }
   public override double area()
   {
      Area = Length * Length * Math.Sqrt(3) / 4;
      return Area;
   }
   public override double perimeter()
   {
      Perimeter = 3 * Length;
      return Perimeter;
   }
}

и класс Circle («Окружность» — задается диаметр):

class Circle : Figure
{
   public Circle(double len) : base(len) {  }
   public override double area()
   {
      Area = Math.PI*Length*Length;
      return Area;
   }
   public override double perimeter()
   {
      Perimeter = 2 * Math.PI * Length;
      return Perimeter;
   }
}

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

В классе Program( ) создадим соответствующие объекты и вызовем методы классов-наследников:

class Program
{
   static void Main(string[] args)
   {
      Console.Write("Характерный размер фигуры = ");
      double len = Convert.ToDouble(Console.ReadLine());
      Console.WriteLine();

      Circle c = new Circle(len);
      c.InfoFigure("Круг (радиус)");
      Console.WriteLine(" площадь = {0:###.###}", c.area());
 
      Square q = new Square(len);
      q.InfoFigure("Квадрат");
      Console.WriteLine("сторона квадрата = {0:###.###}", q.Length);

      Triangle t = new Triangle(len);
      t.InfoFigure("Треугольник");
      Console.WriteLine("периметр = {0:###.###}", t.perimeter());
  
      Console.ReadKey();
   }
}

Результат:

Для тренировки добавьте класс Hexagon («Шестиугольник»), сравните полученные результаты с кругом.

Другая реализация принципа полиморфизма предполагает использование интерфейсов.

 

 


NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.


Понравилась статья? Поделиться с друзьями:
5 1 голос
Рейтинг статьи
Подписаться
Уведомить о
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x