Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Создание многоуровневой иерархии классов




В представленных до сих пор примерах программ использовались простые иерар­хии классов, состоявшие только из базового и производного классов. Но в С# мож­но также строить иерархии, состоящие из любого числа уровней наследования. Как упоминалось выше, многоуровневая иерархия идеально подходит для использования одного производного класса в качестве базового для другого производного класса. Так, если имеются три класса, А, В и С, то класс С может наследовать от класса В, а тот, в свою очередь, от класса А. В таком случае каждый производный класс наследует ха­рактерные особенности всех своих базовых классов. В частности, класс С наследует все члены классов В и А.

Для того чтобы показать, насколько полезной может оказаться многоуровневая иерархия классов, рассмотрим следующий пример программы. В ней производный класс Triangle служит в качестве базового для создания другого производного клас­са - ColorTriangle. При этом класс ColorTriangle наследует все характерные осо­бенности, а по существу, члены классов Triangle и TwoDShape, к которым добавляет­ся поле color, содержащее цвет треугольника.

Листинг 11.13

// Многоуровневая иерархия классов.

 

using System;

 

class TwoDShape

{

double width;

double height;

 

// Конструктор, используемый по умолчанию.

public TwoDShape()

{

Width = Height = 0.0;

}

 

// Конструктор для класса TwoDShape.

public TwoDShape(double w, double h)

{

Width = w;

Height = h;

}

 

// Сконструировать объект равной ширины и высоты.

public TwoDShape(double x)

{

Width = Height = x;

}

 

// Свойства ширины и высоты объекта.

public double Width

{

get { return width; }

set { width = value < 0? -value: value; }

}

 

public double Height

{

get { return height; }

set { height = value < 0? -value: value; }

}

 

public void ShowDim()

{

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

Width + " и " + Height);

}

}

 

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

class Triangle: TwoDShape

{

string Style; // закрытый член класса

 

/* Конструктор, используемый по умолчанию.

Автоматически вызывает конструктор, доступный

По умолчанию в классе TwoDShape. */

public Triangle()

{

Style = "null";

}

 

// Конструктор.

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

Style = s;

}

 

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

public Triangle(double x): base(x)

{

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

}

 

// Возвратить площадь треугольника.

public double Area()

{

return Width * Height / 2;

}

 

// Показать тип треугольника.

public void ShowStyle()

{

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

}

}

 

// Расширить класс Triangle.

class ColorTriangle: Triangle

{

string color;

 

public ColorTriangle(string c, string s,

double w, double h): base(s, w, h) {

color = c;

}

 

// Показать цвет треугольника.

public void ShowColor()

{

Console.WriteLine("Цвет " + color);

}

}

 

class Shapes6

{

static void Main()

{

ColorTriangle t1 =

new ColorTriangle("синий", "прямоугольный", 8.0, 12.0);

ColorTriangle t2 =

new ColorTriangle("красный", "равнобедренный", 2.0, 2.0);

 

Console.WriteLine("Сведения об объекте t1: ");

t1.ShowStyle();

t1.ShowDim();

t1.ShowColor();

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

 

Console.WriteLine();

 

Console.WriteLine("Сведения об объекте t2: ");

t2.ShowStyle();

t2.ShowDim();

t2.ShowColor();

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

}

}

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

Сведения об объекте tl:

Треугольник прямоугольный

Ширина и высота равны 8 и 12

Цвет синий

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

 

Сведения об объекте t2:

Треугольник равнобедренный

Ширина и высота равны 2 и 2

Цвет красный

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

Благодаря наследованию в классе ColorTriangle могут использоваться опреде­ленные ранее классы Triangle и TwoDShape, к элементам которых добавляется лишь та информация, которая требуется для конкретного применения данного класса. В этом отчасти и состоит ценность наследования, поскольку оно допускает повторное использование кода.

Приведенный выше пример демонстрирует еще одно важное положение: ключе­вое слово base всегда обозначает ссылку на конструктор ближайшего по иерархии базового класса. Так, ключевое слово base в классе ColorTriangle обозначает вызов конструктора из класса Triangle, а ключевое слово base в классе Triangle - вызов конструктора из класса TwoDShape. Если же в иерархии классов конструктору базо­вого класса требуются параметры, то все производные классы должны предоставлять эти параметры вверх по иерархии, независимо от того, требуются они самому произ­водному классу или нет.

Порядок вызова конструкторов

В связи с изложенными выше в отношении наследования и иерархии классов мо­жет возникнуть следующий резонный вопрос: когда создается объект производного класса и какой конструктор выполняется первым - тот, что определен в производном классе, или же тот, что определен в базовом классе? Так, если имеется базовый класс А и производный класс В, то вызывается ли конструктор класса А раньше конструктора класса В? Ответ на этот вопрос состоит в том, что в иерархии классов конструкторы вы­зываются по порядку выведения классов: от базового к производному. Более того, этот порядок остается неизменным независимо от использования ключевого слова base. Так, если ключевое слово base не используется, то выполняется конструктор по умол­чанию, т.е. конструктор без параметров. В приведенном ниже примере программы демонстрируется порядок вызова и выполнения конструкторов.

Листинг 11.14

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

 

using System;

 

// Создать базовый класс.

class A

{

public A()

{

Console.WriteLine("Конструирование класса A.");

}

}

 

// Создать класс, производный от класса A.

class B: A

{

public B()

{

Console.WriteLine("Конструирование класса B.");

}

}

 

// Создать класс, производный от класса B.

class C: B

{

public C()

{

Console.WriteLine("Конструирование класса C.");

}

}

 

class OrderOfConstruction

{

static void Main()

{

C c = new C();

}

}

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

Конструирование класса А.

Конструирование класса В.

Конструирование класса С.

Как видите, конструкторы вызываются по порядку выведения их классов.

Если хорошенько подумать, то в вызове конструкторов по порядку выведения их классов можно обнаружить определенный смысл. Ведь базовому классу ничего не из­вестно ни об одном из производных от него классов, и поэтому любая инициализация, которая требуется его членам, осуществляется совершенно отдельно от инициализа­ции членов производного класса, а возможно, это и необходимое условие. Следова­тельно, она должна выполняться первой.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...