Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lec

.pdf
Скачиваний:
24
Добавлен:
24.03.2015
Размер:
3.43 Mб
Скачать

выполнения нет деления объекта на предка и потомка – это единый объект.

Агрегация – аналог производства изделия методом «отверточной сборки». Изготовленные по отдельным чертежам детали (объекты) собираются в более сложное изделие (объект). Класс-контейнер – это сборочный чертеж изделия, определяющий его составные части. На этапе выполнения сохраняется четкое деление объекта на контейнер и часть. Это самостоятельные объекты.

Владелец

 

Человек

 

 

 

чел

 

фам

ном

 

 

 

 

 

 

 

Инфо()

 

Показать()

 

 

 

 

 

2

 

1

 

 

 

Создать объект

 

Создать объект

 

 

100

А777АА-99RUS

Инфо()

«Петров»

Показать()

3

включить объект

 

100

 

 

 

 

Рис.5

class Человек

{

public string фам;

public Человек(string фам)

{

this.фам = фам;

}

public void Показать()

{

Console.WriteLine("Я - человек: " + фам);

}

}

class Владелец

{

public Человек чел; private string ном;

public Владелец(Человек чел, string ном)

{

this.чел = чел; this.ном = ном;

}

131

public void Инфо()

{

Console.WriteLine("Я - владелец: "+чел.фам+" --> " + ном);

}

}

class Program

{

static void Main(string[] args)

{

Человек ч = new Человек("Петров");

Владелец вл = new Владелец(ч,"A777AA-99RUS");

вл.чел.Показать(); //Я - человек: Петров

вл.Инфо();

//Я - владелец: Петров --> A777AA-99RUS

}

}

3. Наследование как средство изменения базового класса

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

Синтаксически это реализуется как определение в классе-потомке метода с тем же именем, составом параметров и возвращаемым значением, что и в базовом классе.

ссылка

 

 

 

ссылка

 

Класс 1

100

 

 

 

200

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

int

F (int x) {…}

 

 

 

 

 

 

 

 

ссылка

 

 

 

 

ссылка

Класс 2

 

Класс 3

 

100

 

 

 

 

 

 

 

 

 

 

 

 

 

 

200

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

new int F (int x) {…}

 

override int F (int x) {…}

 

 

 

 

 

 

 

 

 

Создать объект

ОБЪЕКТ

100

Создать объект

ОБЪЕКТ

200

Рис.6

132

С# поддерживает два способа переопределения метода, определенного в базовом классе на метод, определенный в классе-потомке (Рис.6):

1.new – новая версия метода. Решение о вызываемом методе принимается по типу ссылки. Через ссылку класса-предка вызывается метод, определенный в классе предке, а через ссылку класса-потомка вызывается метод, определенный в классе-потомке.

2.override – метод, заменяющий метод предка. Метод может быть вызван через ссылку класса-потомка или ссылку базового класса. Решение

овызываемом методе принимается по типу объекта, на который указывает ссылка. Для реализации этого способа метод в классе-предке должен быть объявлен как виртуальный (virtual).

class Человек

{

protected string фам; public Человек(string фам)

{

this.фам = фам;

}

public virtual void Показать()

{

Console.WriteLine("Я - человек: " + фам);

}

}

class Студент:Человек

{

private string вуз;

public Студент(string фам, string вуз):base(фам)

{

this.вуз = вуз;

}

}

class Владелец: Человек

{

private string ном;

public Владелец(string фам, string ном): base(фам)

{

this.ном = ном;

}

public new void Показать()

{

Console.WriteLine("Я - владелец: " + фам + " --> " + ном);

}

}

class Служащий: Человек

{

private string фирма;

public Служащий(string фам, string фирма): base(фам)

{

this.фирма = фирма;

}

133

public override void Показать()

{

Console.WriteLine("Я - служащий: "+фам +" ____ "+ фирма);

}

}

class Program

{

static void Main(string[] args)

{

Человек ч;

Студент ст = new Студент("Иванов","ВШЭ");

Владелец вл = new Владелец("Петров", "A777AA-99RUS"); Служащий сл = new Служащий("Сидоров", "Рога и копыта");

ч = ст;

//Вызов метода предка

ч.Показать();

//Я - человек:

Иванов

ст.Показать();

//Вызов метода предка

//Я - человек: Иванов

ч = вл;

//Вызов метода предка

ч.Показать();

//Я - человек:

Петров

вл.Показать();

//Вызов метода наследника

//Я - владелец: Петров --> A777AA-99RUS

ч = сл;

//Вызов метода наследника

ч.Показать();

//Я - служащий: Сидоров ____ Рога и копыта сл.Показать(); //Вызов метода наследника //Я - служащий: Сидоров ____ Рога и копыта

}

}

Применение вызова переопределенного метода override позволяет просто решить проблему определения вызываемого метода при хранении в массиве объектов разного типа. Массив организуется как массив ссылок базового типа. Вызываемый метод определяется автоматически по типу объекта, на который указывает ссылка.

Метод в базовом классе может быть объявлен как абстрактный. Такой метод не содержит реализации – тела. Это только заголовок. Другими словами, базовый класс только декларирует общее поведение, а реализовать его обязаны потомки. В этом отличие абстрактных методов от виртуальных. Виртуальный метод может, но не обязан быть переопределен в потомках. Абстрактный метод должен быть переопределен в клас- се-потомке в обязательном порядке.

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

abstract class ИмяКласса

{

……………………………

}

134

Потомки обязаны переопределять абстрактный метод с модификатором override (new невозможно, т.к. у предка нет никакой версии реализации метода).

abstract class Человек

{

protected string фам; public Человек(string фам)

{

this.фам = фам;

}

public abstract void Показать();

}

class Студент:Человек

{

private string вуз;

public Студент(string фам, string вуз):base(фам)

{

this.вуз = вуз;

}

public override void Показать()

{

Console.WriteLine("Я - студент: " + фам + " " + вуз);

}

}

class Владелец: Человек

{

private string ном;

public Владелец(string фам, string ном): base(фам)

{

this.ном = ном;

}

public override void Показать()

{

Console.WriteLine("Я - владелец: " + фам + " --> " + ном);

}

}

class Служащий: Человек

{

private string фирма;

public Служащий(string фам, string фирма): base(фам)

{

this.фирма = фирма;

}

public override void Показать()

{

Console.WriteLine("Я - служащий: "+фам + " ____ " + фирма);

}

}

135

class Program

{

static void Main(string[] args)

{

Человек ч;

Студент ст = new Студент("Иванов","ВШЭ");

Владелец вл = new Владелец("Петров", "A777AA-99RUS"); Служащий сл = new Служащий("Сидоров", "Рога и копыта"); ч = ст; ч.Показать(); //Вызов метода наследника

//Я - студент: Иванов ВШЭ ст.Показать(); //Вызов метода наследника //Я - студент: Иванов ВШЭ

ч = вл; ч.Показать(); //Вызов метода наследника

//Я - владелец: Петров --> A777AA-99RUS

вл.Показать(); //Вызов метода наследника

//Я - владелец: Петров --> A777AA-99RUS

ч = сл; ч.Показать(); //Вызов метода наследника

//Я - служащий: Сидоров ____ Рога и копыта сл.Показать(); //Вызов метода наследника //Я - служащий: Сидоров ____ Рога и копыта

}

}

Объекты абстрактного класса создать невозможно.

136

ИСКЛЮЧЕНИЯ И ОТЛАДКА

1. Традиционные способы обработки ошибок. Понятие «Структурная обработка исключений».

Многие системные функции возвращают значение, указывающее на успешное или безуспешное выполнение функции. Однако такой способ извещения программы имеет ряд недостатков:

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

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

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

Для доступа прикладных программ к информации о возникшем исключении в Windows (начиная с NT) разработан специальный механизм,

называемый структурной обработкой исключений.

Исключительная ситуация (или исключение) — это ошибка, ко-

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

Структурная обработка исключений — это метод, применяемый

Windows для обработки как программных, так и внутренних аппаратных исключений.

Средство обработки исключений Windows не зависит от используемого языка программирования: один и тот же механизм используется для всех языков.

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

2. Организация обработки исключений в С#

Основная идея обработки исключений состоит в том, что в программе можно определить блок кода, именуемый обработчиком исключений, который автоматически будет получать управление при возникновении определенной ошибки. Обработчик исключений оформляется в виде catch-блока.

В этом случае не обязательно проверять результат выполнения каждой конкретной операции или метода вручную.

Программные инструкции, которые нужно проконтролировать на предмет исключений, помещаются в try-блок.

137

Программа

 

Метод,

 

 

CLR

 

 

Ошибка

 

 

Система динами-

 

 

ческого управле-

 

 

ния

 

 

Аварийное

Рис. 1. Без обработки исключения

завершение

Программа

 

Метод,

 

 

 

 

CLR

try

 

Ошибка

{

Exception

 

}

Система динами-

 

 

 

catch

ческого управле-

 

ния

 

{

 

 

}

 

 

Рис.2. Обработка исключения

 

Программа

 

 

 

 

Метод

try

 

Исключений

{

 

}

 

нет

 

 

catch

 

 

{

 

 

}

 

 

Рис.3 Безошибочное выполнение

 

138

В С# исключения представляются классами, выведенными из встроенного класса исключений Exception.

Наследниками класса Exception являются классы SystemException и ApplicationException, которые делят исходные исключения на две группы.

Exception

SystemException ApplicationException

(генерирует CLR)

(генерируют прикладные програм-

мы)

 

Формат записи try/catch-блоков: try

{

// Блок кода, подлежащий проверке на наличие ошибок.

}

 

catch

( ExcepType1 e )

{

 

//

Обработчик исключения типа ExcepTypel.

}

 

catch ( ExcepType2 e )

{

// Обработчик исключения типа ЕхсерТуре2.

}

ЕхсерТуре — это тип сгенерированного исключения. е – экземпляр типа ЕхсерТуре.

Варианты catch-блоков: catch ( ExcepType )

{

// Обработчик исключения типа ExcepTypel.

}

catch ( IOException e )

{

// Обработчик всех исключений ввода-вывода

}

catch ( SystemException e )

{

139

// Обработчик всех системных исключений

}

catch ( Exception e )

{

//Обработчик всех исключений.

//Передается информация об исключении

}

catch ()

{

//Обработчик всех исключений.

//Информация об исключении не передается

}

Системные исключения класса SystemException

Производный класс

Описание

 

 

ArithmeticException

Ошибка в арифметических операциях

 

или операциях преобразования (пре-

 

док

DivideByZeroException

и

 

OverFlowException)

 

ArrayTypeMismatchException

Тип сохраняемого значения несо-

 

вместим с типом массива

 

DivideByZeroException

Попытка деления на нуль

 

FormatException

Попытка передать в метод аргумент

 

неверного формата

 

IndexOutOfRangeException

Индекс массива оказался вне диапа-

 

зона

 

 

 

InvalidCastException

Неверно

 

выполнено динамическое

 

приведение типов

 

OutOfMemoryException

Обращение к оператору new оказа-

 

лось неудачным из-за недостаточного

 

объема свободной памяти

 

OverflowException

Имеет место арифметическое пере-

 

полнение

и используется оператор

 

checked

 

 

 

StackOverflowException

Переполнение стека

 

NullReferenceException

Была сделана попытка использовать

 

нулевую ссылку, т.е. ссылку, которая

 

не указывает ни на какой объект

 

IOException

Ошибка ввода-вывода

 

TypeInitializationExeption

Отсутствует блок catch для обработки

 

исключения, сгенерированного ста-

 

тическим конструктором

 

3. Свойства и методы класса Exception

140

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]