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

Объект — треугольник Площадь равна 48

Объект — прямоугольник Площадь равна 100

Площадь равна 40

Объект — треугольник Площадь равна 24.5

Объект — общая форма

Метод Area() должен быть переопределен Площадь равна 0

Рассмотрим данный пример программы более подробно. Прежде всего, метод Area () объявляется как virtual в классе TwoDShape и переопределяется в классах Triangle и Rectangle по объяснявшимся ранее причинам. В классе TwoDShape метод Area () реализован в виде заполнителя, который сообщает о том, что пользователь данного метода должен переопределить его в производном классе. Каждое переопределение метода Area () предоставляет конкретную его реализацию, соответствующую типу объекта, инкапсулируемого в производном классе. Так, если реализовать класс для эллипсов, то метод Area () должен вычислять площадь эллипса.

У программы из рассматриваемого здесь примера имеется еще одна примечательная особенность. Обратите внимание на то, что в методе Main () двумерные формы объявляются в виде массива объектов типа TwoDShape, но элементам этого массива присваиваются ссылки на объекты классов Triangle, Rectangle и TwoDShape. И это вполне допустимо, поскольку по ссылке на базовый класс можно обращаться к объекту прризводного класса. Далее в программе происходит циклическое обращения к элементам данного массива для вывода сведений о каждом объекте. Несмотря на всю свою простоту, данный пример наглядно демонстрирует преимущества наследования и переопределения методов. Тип объекта, хранящийся в переменной ссылки на базовый класс, определяется во время выполнения и соответственно обусловливает дальнейшие действия. Так, если объект является производным от класса TwoDShape, то для получения его площади вызывается метод Area () . Но интерфейс для выполнения этой операции остается тем же самым независимо от типа используемой двумерной формы.

Применение абстрактных классов

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

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

Абстрактный метод создается с помощью указываемого модификатора типа abstract. У абстрактного метода отсутствует тело, и поэтому он не реализуется в базовом классе. Это означает, что он должен быть переопределен в производном классе, поскольку его вариант из базового класса просто непригоден для использования. Нетрудно догадаться, что абстрактный метод автоматически становится виртуальным и не требует указания модификатора virtual. В действительности совместное использование модификаторов virtual и abstract считается ошибкой.

Наши рекомендации