Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Использование абстрактных классов




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

бланк", который унаследуют все производные классы, причем каждый из них запол-

нит этот "бланк" собственной информацией. Такой класс определяет "суть" методов,

которые производные классы должны реализовать, но сам при этом не обеспечивает

реализации одного или нескольких методов. Подобная ситуация может возникнуть,

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

проиллюстрирован версией класса TwoDShape (из предыдущей программы), в которой

определение метода агеа() представляло собой "заглушку", поскольку в нем пло-

щадь фигуры не вычислялась и, естественно, не отображалась.

В будущем, создавая собственные библиотеки классов, вы убедитесь, что отсутст-

вие у метода четкого определения в контексте своего (базового) класса, не является

чем-то необычным. Описанную ситуацию можно обработать двумя способами. Один

из них, который продемонстрирован в предыдущем примере, — вывод предупреж-

дающего сообщения. И хотя такой подход может быть полезным в определенных об-

стоятельствах (например, при отладке программы), все же он не соответствует уровню

профессионального программирования. Существует и другой способ. Наша цель —

заставить производные классы переопределить методы, которые в базовом классе не

имеют никакого смысла. Рассмотрим класс Triangle. Им нельзя пользоваться, если

не определен метод area (). Необходимо иметь средство, благодаря которому произ-

водный класс обязательно переопределит все необходимые методы. Этим средством в

С# является абстрактный метод.

Абстрактный метод создается с помощью модификатора типа a b s t r a c t . Абстракт-

ный метод не содержит тела и, следовательно, не реализуется базовым классом. По-

этому производный класс должен его переопределить, поскольку он не может исполь-

зовать версию, предложенную в базовом классе. Нетрудно догадаться, что абстракт-

ный метод автоматически является виртуальным, поэтому и нет необходимости в

использовании модификатора v i r t u a l . Более того, совместное использование моди-

фикаторов v i r t u a l и abstract считается ошибкой.

Для объявления абстрактного метода используйте следующий формат записи.

abstract ТИП ИМЯ(список_параметров) ;

Как видите, тело абстрактного метода отсутствует. Модификатор a b s t r a c t можно

использовать только применительно к обычным, а не к static-методам. Свойства

также могут быть абстрактными.

Класс, содержащий один или несколько абстрактных методов, также должен быть

объявлен как абстрактный с помощью спецификатора abstract, который ставится

перед объявлением class. Поскольку абстрактный класс нереализуем в полном объе-

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

дать объект абстрактного класса с помощью оператора new приведет к возникновению

ошибки времени компиляции.

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

страктные методы базового класса. В противном случае такой производный класс

также должен быть определен как абстрактный. Таким образом, атрибут abstract на-

следуется до тех пор, пока реализация класса не будет полностью достигнута.

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

TwoDShape. Поскольку для не определенной заранее двумерной фигуры понятие

площади не имеет смысла, в следующей версии предыдущей программы метод

area () в классе TwoDShape объявляется как абстрактный, как, впрочем, и сам класс

TwoDShape. Безусловно, это означает, что все классы, выведенные из TwoDShape,

должны переопределить метод area ().

// Создание абстрактного класса.

using System;

abstract class TwoDShape {

double pri_width; // Закрытый член,

double pri_height; // Закрытый член,

string pri_name; // Закрытый член.

// Конструктор по умолчанию,

public TwoDShape() {

width = height = 0.0;

name = "null";

}

// Конструктор с параметрами.

public TwoDShape(double w, double h, string n) {

width = w;

height = h;

name = n;

}

// Создаем объект, у которого ширина равна высоте,

public TwoDShape(double x, string n) {

width = height = x;

name = n;

// Создаем объект из объекта,

public TwoDShape(TwoDShape ob) {

width = ob.width;

height = ob.height;

name = ob.name;

}

// Свойства width, height и name,

public double width {

get { return pri_width; }

set { pri_width = value; }

}

public double height {

get { return pri_height; }

set { pri_height = value; }

310 Часть I. Язык С#

http://openlib.org.ua/

public string name {

get { return pri__name; }

set { pri_name = value; }

}

public void showDim() {

Console.WriteLine("Ширина и высота равны " +

width + " и " + height);

}

// Теперь метод агеа() абстрактный,

public abstract double area();

}

// Класс треугольников, производный ачг класса TwoDShape.

class Triangle : TwoDShape {

string style; // Закрытый член.

// Конструктор по умолчанию,

public Triangle() {

style = "null";

}

// Конструктор с параметрами.

public Triangle(string s, double w, double h) :

base(w, h, "triangle") {

style = s;

}

// Создаем равнобедренный треугольник.

public Triangle(double x) : base(x, "треугольник") {

style = "равнобедренный";

}

// Создаем объект из объекта. ,

public Triangle(Triangle ob) : base(ob) {

style = ob.style;

}

// Переопределяем метод агеа() для класса Triangle,

public override double area() {

return width * height / 2 ;

}

// Отображаем тип треугольника,

public void showStyle() {

Console.WriteLine("Треугольник " + style);

}

}

// Класс прямоугольников, производный от класса TwoDShape.

class Rectangle : TwoDShape {

// Конструктор с параметрами.

public Rectangle(double wf double h) :

base(w, h, "прямоугольник"){ }

// Создаем квадрат.

public Rectangle (ckmfcrle x) :

base(xf "прямоугольник") { }

// Создаем объект из объекта.

public Rectangle(Rectangle ob) : base(ob) { }

// Метод возвращает значение true, если

// прямоугольник является квадратом,

public bool isSquareO {

if (width ===== height) return true;

return false;

// Переопределяем метод агеа() для класса Rectangle,

public override double area() {

return width * height;

class AbsShape {

public static void Main() {

TwoDShape [] shapes == new TwoDShape[4];

shapes[0] = new Triangle("прямоугольный", 8.0, 12.0);

shapes[1] = new Rectangle(10);

shapes[2] = new Rectangle(10, 4);

shapes[3] = new Triangle (7.0);

for(int i=0; i < shapes.Length; i++) {

Console.WriteLine("Объектом является " +

shapes[i].name);

Console.WriteLine("Площадь равна " +

shapes[i 3.area());

Console.WriteLine();

Как продемонстрировано этой программой, все производные классы должны или

переопределить метод area (), или также объявить себя абстрактными. Чтобы убе-

диться в этом, попробуйте создать производный класс, который не переопределяет

метод area (). Вы тут же (т.е. во время компиляции) получите сообщение об ошибке.

Конечно, мы можем создать объектную ссылку типа TwoDShape, что и делается в

программе. Однако теперь нельзя объявить объект типа TwoDShape. Поэтому в методе

Main () размер массива shapes сокращен до 4, и больше не создается "заготовка для

фигуры" в виде объекта класса TwoDShape.

Обратите также внимание на то, что класс TwoDShape по-прежнему включает ме-

тод showDimO, объявления которого не коснулся модификатор a b s t r a c t . Ведь впол-

не допустимо для абстрактного класса содержать конкретные (а не только абстракт-

ные) методы, которые производный класс может использовать "как есть". И только

методы, объявленные с использованием ключевого слова abstract, должны переоп-

ределяться производными классами.










Последнее изменение этой страницы: 2018-05-27; просмотров: 202.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...