logo
lab_rab_6

8.3. Абстрактные классы

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

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

Вернемся к уже рассматривавшемуся примеру иерархии классов – Figure, Rectangle и Circle. В этом примере базовый класс Figure предоставляет реализацию по умолчанию виртуального метода Build, замещенного в производных классах. Однако в нашей программе до сих пор существует потенциальный источник ошибок: мы можем создавать объекты базового класса Figure, что и было показано в листинге 8.6 в строках

Figure[] obj = new Figure[3];

obj[0] = new Figure();

«Просто фигур» у нас быть не должно — каждой из возможных категорий фигуров у нас соответствует производный класс. Поэтому вполне логичным будет просто запретить создание объектов класса Figure. В языке С# для этого достаточно объявить класс абстрактным:

// Объявляем класс Figure абстрактным

abstract public class Figure

{

// Открытые интерфейсы и внутренние данные класса

}

Теперь при попытке создания объекта класса Figure компилятор будет выдавать сообщение об ошибке.

// Ошибка! Нельзя создавать экземпляры абстрактного класса

Figure X = new Figure ();

После того, как мы объявили класс абстрактным, можно определить в нем любое количество абстрактных методов. Абстрактные методы – это методы, имеющие пустые тела. При объявлении абстрактного метода используется следующая форма синтаксиса:

аbstract тип имя (список параметров);

В этом объявлении отсутствует тело метода. Например, в абстрактном классе Figure может быть определен следующий метод:

public abstract void Build ();

Этот метод не имеет определения, так как нельзя нарисовать геометрическую фигуру вообще. Каждый производный от абстрактного класс должен выполнять обязательное переопределение метода Build. Переопределение абстрактного метода в производных классах ничем не отличается от перегрузки виртуальных методов (листинг 8.7).

Листинг 8.7. Переопределение абстрактного метода базового класса в производных классах

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ConsoleApplication1

{

// объявление класса Figure как абстрактного

abstract class Figure

{

public abstract void Build();

}

class Rectangle : Figure

{

// переопределение абстрактного метода Build в классе Rectangle

public override void Build()

{

Console.WriteLine("Строим прямоугольник");

}

}

class Circle : Figure

{

// переопределение абстрактного метода Build в классе Circle

public override void Build()

{

Console.WriteLine("Строим окружность");

}

}

class Program

{

static void Main(string[] args)

{

// в методе Main теперь можно создавать объекты только производных //классов

Rectangle obj1 = new Rectangle();

obj1.Build();

Circle obj2 = new Circle();

obj2.Build();

}

}

}