WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!

Pages:     | 1 | 2 || 4 | 5 |   ...   | 7 |

«Exam 70-310 and 70-320 XML Web Services and Server Components WITH VISUAL BASIC AND VISUAL Exam 70-306 and 70-316 DEVELOPING APPLICATIONS WITH VISUAL BASIC AND VISUAL Press Сертификационный ...»

-- [ Страница 3 ] --

Таблица 3-6. Члены класса Collections Имя Описание Представляет уплотненный массив элементов (принимающих значение 1 или 0) Основа для создания пользовательских классов наборов, предоставляет большинство функций, необходимых для обслуживания наборов Набор пар «ключ — значение», упорядоченных по значению хеш-кода ключа Queue Набор объектов, организованный по принципу «первым вошел — первым вышел» Группа объектов, доступных через значение индекса или ключа Stack Набор объектов, организованный по принципу «первым вошел — вышел» Занятие 2 Константы, массивы и наборы Перебор элементов массивов и наборов В Visual Basic и Visual C# имеется специальный синтаксис для перебора эле ментов массивов и наборов в цикле. Оператор For Each (foreach) позволяет пооче редно обработать все элементы массива набора. Это делается следующим обра зом:

Visual Basic Dim As Integer = Dim I As Integer For Each I in Next C# int[] myArray - new int[] foreach (int I in myArray) { } При использовании такого синтаксиса с наборами у всех элементов набора дол жен быть тот же тип, что и у переменной цикла. Если в цикле обратиться к элемен ту набора, который невозможно записать в переменную цикла, генерируется ис ключение Во избежание подобных проблем при работе с набо рами, объекты разных типов, переменную цикла следует с типом Object, а также проверять допустимость типа элемента набора с помощью оператора Basic или метода (Visual C#):

Visual Basic Этот пример предполагает, что - это набор типа ' содержащий, помимо строк, объекты других типов.

Dim о as Object For Each о myList If TypeOf о Is String Then If Next Visual C# Этот пример предполагает, что myList - это набор типа помимо строк, других foreach (object о in myList) { if == { MessageBox.

Типы и члены Важно отметить, что при использовании цикла For Each ссылка на эле мент набора или которая содержится в переменной цикла, доступна толь ко для чтения. Следовательно, этот цикл не позволяет модифицировать элементы массивов и наборов. Чтобы получить возможность модифицировать элементы мас сива или набора при переборе их в следует использовать цикл (for) образом:

Visual Dim As Integer Dim x As Integer x = 0 to += Next Visual int[] int[] (int x = 0;

x <= x++) { ++;

Резюме • Константы и перечисления делают код более читабельным и устойчивым к ошибкам, часто употребляемые значения понятными пользователю именами. Константы определяют с помощью ключевого слова Const для объявления перечислений применяют ключевое слово (епит). Константы могут быть объявлены на основе любых типов данных, а перечисления — только на основе целочисленных типов.

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

• Наборы позволяют работать с группами объектов одного или разных типов, Классов наборов несколько, все они располагаются в пространстве имен Sys tem, Collections. Класс предоставляет основную функ циональность для работы с наборами, достаточную для решения типовых задач.

• Оператор For Each (foreach) позволяет перебирать значения элементов массива или коллекции в цикле, но не позволяет модифицировать значения элементов.

Чтобы получить такую возможность, необходимо применить оператор (for).

3 Реализация Занятие 3. Реализация свойств Свойства — это члены классов, доступ к переменным или класса. Свойства напоминают одновременно поля и методы. Синтаксис доступа к свойствам тот же, что и для полей, только при получении или установке свойства на самом деле вызывается специальный метод, который и выполняет запрошенное действие. У свойства также может быть код, проверяющий значение перед установ кой свойства и любые другие действия, необходимые Изучив материал этого занятия, вы сможете:

рассказать, как реализуют свойства;

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

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

Продолжительность занятия - около 30 минут.

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

Visual Basic Установить Text = "Text Property" Dim As String Получить значение TextBoxl.Text и присвоить его = TextBoxl.Text Visual // Установить свойство textBoxl.Text = "Text property";

rnyString;

// Получить значение TextBoxl.Text и присвоить его переменной myString myString На этом уровне свойства выглядят и работают, как поля, но код, который «сто ит» за свойствами, несколько сложнее. Свойство состоит из двух специальных ме тодов: получателя (getter) и установщика (setter). Далее показан пример объявле ния свойства Visual Basic Создать закрытую локальную переменную для хранения значения свойства.

Private As String Глава ' Реализация свойства Public Property As String Get Вернуть значение локальной переменной.

mText End Get Set(ByVal Value As ' значение локальной переменной, mText Value End Set End Property C# // Создать закрытую локальную переменную для хранения значения private string mText;

// Реализация свойства public string get ;

// Вернуть значение локальной return mText;

:

set // Установить значение локальной переменной.

mText = value;

В методе-установщике применяется специальное ключевое слово новое присваиваемое данному свойству. Свойства от крывают доступ к объектам любого типа, а также к массивам и наборам. Объект или значение, предоставляемое свойством, обычно хранится в закрытой (private) локальной переменной как т Text из предыдущего примера);

при получении свойства его значение извлекается из этой переменной.

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

Visual Basic Private As Integer Public Property Length() As Integer Get Вернуть значение локальной переменной.

3 Реализация Return Get Set(ByVal Value As Integer) Проверяем, не превышает ли значение заданный предел (32).

If Value > & too large a value this Else mLength = Value End If End Set End Property C# private int mLength;

int Length { get !

// Вернуть значение локальной переменной.

return mLength;

se // не превышает ли значение заданный предел (32).

if (value > 32) value. + is too large a value for this else = value;

Как создать свойство Объявите закрытое поле или объект, в котором будет храниться значение (или объект), возвращаемое этим свойством.

2. Напишите для свойства значение.

3. Добавить, если необходимо, дополнительный код проверки в метод, устанавли вающий значение или получающий значение свойства.

Свойства, доступные только для чтения или только для записи Иногда необходимо создать значение которого клиент получит, но не сможет модифицировать после того, как оно было установлено во время инициа класса. Еще реже требуются свойства, которые не доступны для чтения, но доступны для модификации. Такие свойства называют соответственно доступными только для чтения (read-only) и только для записи (write-only).

Типы и члены Глава Создание свойств, доступных только для чтения Процедура создания подобных свойств мало отличается от таковой для обычных свойств. Чтобы создать на Visual свойство, доступное только для чтения, доста точно определить свойство, у которого имеется метод Get, а метод Объявляя подобное свойство на Basic необходимо пометить его клю чевым словом метод Set также следует опустить. В обоих языках закры тую переменную, в которой хранится значение свойства, необходимо объявлять с ключевым словом ReadOnly (readonly). Вот пример свойства, доступного только для чтения:

Basic Private as Integer Public Readonly Property As Integer Get End Get End Property Visual private readonly public int { get { return } :

Поскольку переменная, хранящая значение свойства, доступна только для чте ния, ее нельзя модифицировать в коде. Начальное значение для такой переменной необходимо задавать в конструкторе класса.

Как создать свойство, доступное только для чтения Объявите закрытую переменную, в которой будет храниться значение свойства, пометив ее ключевым словом ReadOnly (readonly).

1. Напишите реализацию свойства, предоставив только метод для получения зна чения свойства, а его метод опустите. В Visual Basic это свойство также необходимо пометить ключевым словом 3. Добавьте к конструктору класса, членом которого является переменная свой ства, код, ей начальное значение.

Свойства, доступные только для записи Можно создать свойство, значение которого клиент сумеет модифицировать, но не сможет прочитать, однако такие свойства требуются очень редко. Свойства, доступ ные только для записи, применяются для локализации форм. Например, если за дать другой регион, код свойства соответствующим образом изменит форму, а чи тать эти свойства не обязательно.

Свойства, доступные только для записи, создаются практически так же, как свойства, доступные только для чтения. Для хранения значения этого свойства так же требуется объявить закрытую локальную переменную, но в этом случае следует реализовать только метол, устанавливающий значение свойства, а метод, получаю его, опустить. В Visual Basic подобное свойство необходимо пометить ключевым словом Как создать свойство, доступное только для записи 1. Объявите закрытую переменную для хранения значения 2. Напишите реализацию свойства, предоставив только метод, значение свойства. В этот метод можно поместить любой код, который следует выполнить при изменении значения свойства. Кроме того, в Visual Basic это свойство следует пометить ключевым словом WriteOnly, Параметризованные свойства Как правило, разработчики создают свойства, единственное значе ние или объект. В Basic можно создавать свойства, которые принимают параметры. Как правило, такие свойства возвращают диапазон (или массив) значе ний. Рассмотрим для примера объект Engine, представляющий двигатель по-английски — двигатель). У реального двигателя может быть несколько ров, аналогично объект Engine включает несколько Чтобы не пи сать код для доступа к каждому из этих объектов, создают свойство полу чающее или значение любого объекта Cylinder в зависимости от переданного параметра.

Объявление параметризованных свойств не отличается от такового для обычно го свойства, единственное отличие — в объявлении параметра. Далее код методов, и устанавливающих значение свойства. Вот пример парамет ризованного свойства, открывающего доступ к массиву объектов:

Visual Basic Создать массив для хранения значений свойства.

Private mCylinders(7) As Cylinder Public Property i As Integer) As Cylinder Get Проверить параметр, переданный при обращении к свойству.

If I > 7 Then value out of Exit Property If Если объект не создать его.

If Is Nothing Then - New If Return mCylinders(i) End Get Value As Cylinder) ' Проверить параметр, переданный при обращении к свойству.

If > 28 Типы и члены value out of Exit End If - Value Set End Property Visual C# не поддерживает параметризованные свойства, за исключением ин дексаторов, о которых пойдет речь в следующем разделе.

Свойства по умолчанию и индексаторы Компоненту, написанному на Visual Basic допустимо назначить свойство по умолчанию. Оно непременно должно быть параметризованным. Обычно это свой ство возвращает диапазон, массив или набор значений. Назначать объекту свой ство по умолчанию имеет смысл, только если его основной функцией является хра нение других объектов и предоставление к ним доступа.

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

Visual Basic Этот пример предполагает, что Item свойством по умолчанию для объекта = "Default properties!" Поскольку для обращения к свойству по умолчанию достаточно указать имя объекта, у класса может быть не более одного свойства по умолчанию. В объявле нии свойства по умолчанию указывают ключевое слово Visual Basic Public Default Property Item(I As Integer) As String Реализация опущена End Property В Visual эквивалентом свойств по умолчанию являются индексаторы. Ин дексатор — это особое свойство, позволяющее получать доступ к группе объектов, указывая только имя объекта, в котором реализован индексатор. В коде класса ин дексатор всегда фигурирует под именем this. Это свидетельствует о том, что для об ращения к индексатору достаточно указать имя объекта, членом которого оно яв ляется. Вот пример простого индексатора:

Visual // Создать массив для хранения значений, // к которым предоставляет доступ индексатор private IntArray;

// Переменная индекса (в квадратных скобках) служит // для указания нужного значения индексатора.

public int this[int index] !

get !

return } set i IntArray[index] = value;

Как создать свойство по умолчанию в Basic Для этого следует создать свойство, объект, заданный переданным ему параметром. Это свойство следует объявлять с клю чевым словом Default.

Как создать индексатор в Visual C# Чтобы создать индексатор, следует объявить свойство с именем this, назначить для него переменную индекса и написать код, значение с ным индексом.

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

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

Visual Private Readonly As New Public Readonly Property As Get Return mWidgets End Get End Property Visual C# private readonly mWidgets new Col lections.

public Widgets Типы и члены { return } этот способ прост и позволяет получать доступ к элементам набора, у него есть один существенный недостаток. Большинство наборов, представленных клас сами из пространства имен System. Collections, мает и возвращает свои элемен ты в виде объектов типа Object. Это означает, что можно добавить в набор (или уда лить из него) объект любого типа. Иными словами, при добавлении к набору новых элементов проверка типов не выполняется, а возвращаемые элементы набора необ ходимо явно приводить к нужному типу. Впрочем, если свойство должно работать с разнородными объектами, этот подход приемлем.

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

Чтобы получить более устойчивое к ошибкам, следует сделать набор доступным через свойство и написать код, выполняющий явное преобразо вание типов и проверку значений, присваиваемых свойству. Это позволит получать из набора элементы с заданным индексом и проверять типы помещаемых в него объектов. Такое свойство в Visual Basic реализуют в виде параметризованного свойства, например, так:

Basic Private as New Public Property As Integer) As Widget Get Return Widget) End Get Set(ByVal Value As Widget) = Value End Set End Property Visual не поддерживает параметризованные свойства, поэтому при исполь зовании этого языка такие свойства реализуют как индексаторы либо в виде пары специальных методов (см. пример кода далее).

C# private mWidgets System. Col ArrayListO;

public Widget GetWidget{int I) return ) public void SetWidget(int I, Widget Wid) { = Wid;

!

Реализация Аналогичным образом создают строго типизированные свойства, доступ к набору однотипных элементов, однако этот способ не лишен недостатков.

Например, при его использовании применять оператор For для перебора элементов набора в цикле, а для всех методов данного свойства, которые должны быть доступными клиенту, потребуется написать оболочку. Нако в этом случае невозможны некоторые отступления от правил раз решенные в Visual C#.

Как создать с проверкой типов • в Visual Basic для этого следует создать воз элемент закрытого (private) набора, заданный индексом, и написать код, преобразующий возвращаемый объект в требуемый тип при функ ции • в Visual C# для этого необходимо создать пару методов, получающих и ливающих элемент закрытого набора, заданный индексом, причем метод жен явно приводить возвращаемый объект к требуемому типу.

Чтобы создать свойство с еще более строгой можно объявить соб ственный класс строго типизированного набора на основе класса System.

ons. Collection Base. Этот класс предоставляет основную функциональность, необхо димую для обслуживания наборов, позволяя создавать собственную реализацию для свойства Созданный таким образом строго типизированный набор удается сде лать доступным непосредственно через свойство (этот прием проиллюстрирован в приведенном выше примере);

при этом вся функциональность наборов останется доступной. Помимо приема только элементов заданного типа, такой набор поддер живает любую другую необходимую функциональность. Наследование рассматри вается в деталях в главе 4, там же вам предлагается упражнение с примером, иллю стрирующим создание строго типизированного набора.

Резюме • Свойства открывают доступ к членам класса (переменным и объектам), позво ляют создавать код, значение свойства при обращении к нему и ряд других действий. Свойства, доступные только для чтения или только для записи, позволяют ограничить доступ клиента к свойствам чтением или записью. Visual Basic также позволяет создавать свойства, принимаю щие параметры и диапазоны значений.

• К значению свойства по умолчанию разрешено не указывая имя этого свойства. Такие свойства должны быть В Visual С# эквивалентом свойств по умолчанию являются индексаторы.

• открывают доступ к группам объектов, поддерживаемых клас сом. Предусмотрено несколько способов реализации подобных свойств, каждый из них обладает своими достоинствами и недостатками:

• простейшее свойство-набор, возвращающее объект-набор из закрытой пере менной;

этот способ наименее устойчив к ошибкам;

• свойство, возвращающее элемент закрытого набора с заданным индексом.

Этот вариант более устойчив к ошибкам, но менее гибок;

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

Типы и Занятие 4. Реализация событий и делегатов События уведомляют о важных происшествиях, случившихся в других частях при ложения. Если где-то в приложении генерируется событие, остальные компоненты приложения получают возможность отреагировать на него исполнением методов, которые называются обработчиками события. В главе 2 мы показали, как писать в Visual Studio обработчики для генерируемых формами и элемента ми управления. На этом занятии вы научитесь объявлять и генерировать в прило жении собственные события, писать для них обработчики, а также динамически подключать и отключать последние во время выполнения.

Изучив материал этого занятия, вы сможете:

объяснить, что такое делегаты и как их создают;

объявлять и генерировать события в приложении;

создавать обработчики событий и связывать их с событиями;

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

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

Сигнатура метода, обрабатывающего событие, должна совпадать с сигнатурой это го события. Иными метод должен принимать аргументы, которые переда ются с событием. Одно событие может обрабатываться несколькими а один метод может обрабатывать несколько событий.

Делегаты Делегаты — это особые классы, работу событий. В сущности, де легат — это указатель на функцию, обеспечивающий контроль типов. Он позволяет передавать ссылку на точку входа метода и исполнять этот метод без традиционно го явного вызова. При объявлении делегата указывают сигнатуру вызываемого им метода и тип возвращаемого результата:

Visual Basic Public Function D As Double) As Integer Visual C# public delegate int D):

В этом примере объявляется делегат вызывающий методы, которые возвращают результат типа (int) и принимают в качестве параметра значение типа Double (double). Чтобы воспользоваться делегатом, необходимо создать его эк земпляр с указанием метода, который он будет вызывать. В Visual этот метод задают по имени, а в Visual Basic применяют оператор который со здает ссылку на адрес метода. Вот примеры:

Visual Basic Это который будет вызывать делегат.

Public Function As As Integer метода опущена, End Function Создать экземпляр делегата который будет вызывать метод aDelegate As New Returnlnt) Visual C# // Это метод, который будет вызывать делегат.

public D) // Создать экземпляр myDelegate, который будет вызывать метод Returnlnt.

public void { nyDelegate aDelegate new.

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

После объявления и инициализации делегат можно вызывать, как обычную фун кцию, чтобы исполнить связанный с ним метод, например:

Visual Basic aDelegate(12345) C# Как создать и вызвать делегат Объявите делегат с сигнатурой, идентичной сигнатуре метода (или методов), для вызова которого он будет использоваться.

2. Создайте экземпляр делегата, ссылающийся на метод с подходящей 3. Вызывайте делегат в коде, ссылаясь на него по имени.

Объявление и генерация событий В главе 2 говорилось, что у форм и элементов управления есть члены-события, ко торые генерируются в обстоятельствах. Например, Click Типы и члены генерируется в ответ на мышью. В классах можно объявлять собственные события и генерировать их при необходимости.

Объявление событий имеет непосредственное отношение к делегатам. В Visual С# необходимо явно указать тип-делегат, который будет использовать объявляемое событие. В Visual Basic этот механизм по большей части работает «за кулиса ми»;

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

Как объявить событие на Visual Basic Чтобы объявить событие, необходимо указать ключевое слово Event и сигнатуру методов, это событие. При этом можно использовать любые модификаторы доступа: или Protected. Вот пример объявления со бытия:

Basic Public Event Total As Double) Как объявить на Чтобы объявить необходимо указать ключевое слово Event и тип-деле гат, который будет использоваться этим событием. При этом разрешено приме нять любые модификаторы доступа: private или protected. Вот пример объявления события:

Visual C# public delegate void public event Объявив допустимо генерировать его в коде в ответ на соответствую щие обстоятельства. Например, компонент, представляющий банковский счет, будет генерировать событие Overdrawn всякий раз, когда баланс счета опустится ниже Как генерировать событие в Visual Basic Для события следует указать ключевое слово за которым следует имя генерируемого события и все необходимые параметры (в скобках), например:

Basic.

RaiseEvent Как в Visual C# Чтобы генерировать событие, достаточно указать его имя (как при вызове мето да) и все необходимые параметры (в скобках), например:

Visual Занятие 4 Реализация событий и Реализация обработчиков событий Чтобы генерировать объявленное событие, необходимо с ним один или не сколько обработчиков. Обработчик события — это метод, который вызывается по средством делегата всякий раз, когда генерируется соответствующее событие. Что бы этот механизм работал, необходимо связать обработчики с обрабатываемыми событиями. Если в программе на Visual Basic генерировать событие, с кото рым не связан ни один обработчик, попросту ничего не произойдет;

в Visual же подобные действия закончатся ошибкой.

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

Создание событий в Visual Basic Обработчик события в Visual Basic следует объявлять как он не может возвращать значения. Процедуру связывают с обрабатываемым ей собы тием при помощи ключевого слова После следует имя со бытия и указатель на метод, с которым будет связано это событие. Указатель на метод создают оператором AddressOf, например, так:

Visual Private Sub sender As e As AddHandler AddressOf End Sub Ключевое слово AddHandler не разрешается применять декларативно — только внутри метода. В силу этих причин связь между событием и его обработчиком со здается только во время выполнения. Чтобы связь между обработчиком и событием существовала на протяжении всего срока жизни объекта, следует поместить ключе вое слово AddHandler в конструктор объекта.

В Visual Basic можно связывать обработчики с обрабатываемыми ими со бытиями и во время разработки. Для этого применяется конструкция При этом объект-приемник события необходимо объявить с ключевым словом которое разрешает ему регистрироваться для уведомления о событиях та, указанного в поле Конструкция Handles завершает объявление метода, в ней определяют событие объекта, обрабатываемое этим методом, например:

Visual Basic Public Sub Handles Реализация опущена End Sub Типы и Создание обработчиков событий на C# В отличие от Visual Basic в Visual обработчикам событий разрешается воз значение, которое можно присваивать переменной, как это делается при вызове функции. Чтобы связать некоторый метод с событием, следует создать эк земпляр соответствующего делегата, ссылающегося на этот метод, и связать его с событием при помощи оператора Этот оператор также позволяет собы тие с существующим экземпляром делегата, например, так:

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

new // Связать событие с обработчиком при помощи существующего экземпляра делегата.

= += calc;

Для событий элементов управления и классов из библиотеки базовых классов Framework предоставляются делегаты по умолчанию. Чтобы добавить обра ботчик для этих событий вручную, необходимо объявить новый делегат либо со здать новый экземпляр предопределенного типа-делегата. Например, с большин ством элементов управления из пространства имен System, применя ется System, Ниже показан пример, иллюстрирующий назначение обработчика событию Click элемента управления button 1:

Visual C# += new В отличие от Visual Basic в Visual C# нет механизма для декларативного связывания событий с их обработчиками.

Обработка событий в Visual Basic • При помощи ключевого слова свяжите событие с методом, который его будет обрабатывать;

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

• Другой вариант — связать метод с обрабатываемым им событием во время раз работки (при помощи ключевого слова Handles). При этом метод-обработчик должен быть членом объекта, объявленного с ключевым словом With Events.

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

Создание обработчика для группы событий Можно создать метод, способный обрабатывать несколько событий. Обычно это требуется, если несколько экземпляров класса или элементов управления генери руют одинаковые события. Например, если на форме расположена группа кнопок, 4 Реализация сходные функции в приложении, стоит создать единственный ме тод, который будет обрабатывать событие Click всех этих кнопок. гене рировавшую событие, определяют по значению параметра sender.

Связать обработчик с несколькими событиями просто: это делается при ши оператора AddHandler (в Visual Basic а в С# — как и в случае с одним событием.

Этот пример предполагает наличие метода с сигнатурой, подходящей для приема событий Click.

ClickHandler AddHandler AddressOf Visual C# // Этот пример предполагает наличие метода ClickHandler с // подходящей для приема событий Click.

Click new new В Visual Basic для связывания одного обработчика с несколькими событи ям применяют конструкцию Handles, в которой перечисляют (через запятую) все события, с которыми следует связать обработчик:

Visual Basic Private Sub ClickHandler sender As e As Handles Реализация опущена.

Sub События с несколькими обработчиками У события может быть несколько обработчиков. При генерации такого события, все обработчики исполняются в порядке их связывания с этим событием. Так, если с событием х были поочередно связаны в коде обработчики у, z и q, то при ции этого события сначала исполняется обработчик у, затем z и в последнюю оче редь q. В Visual имеется одна особенность: если событие значение, наличии у него нескольких обработчиков, будет возвращен результат исполне ния последнего обработчика.

Чтобы связать с событием несколько обработчиков, достаточно поочередно под ключить их к нужному событию. В Visual Basic это делается декларативно с помощью конструкции Handles. Правда, в этом случае трудно предсказать порядок вызова обработчиков при генерации события;

если важно его знать, лучше лить его экспериментально.

Отключение обработчиков во время выполнения Как уже говорилось, для динамического связывания обработчика с событием при меняется ключевое слово AddHandler (в Visual Basic или оператор (в Visual Возможна и обратная операция — динамический разрыв связи между обработ Типы и члены и событием во время выполнения. Рассмотрим следующий пример. Допус тим, имеется класс, банковский счет, который генерирует собы тие всякий раз, когда владелец счета пытается выписать чек на сумму, превышающую остаток средств на счете. С этим событием можно связать два обработчика: метол Account, вычисляющий размер сбора за предосгавле ние дополнительного кредита в размере суммы, на которую выписан чек, и извещающий владельца счета о превышении кредита (об овердрафте). Метод Char имеет смысл вызывать каждый раз, когда проходит чек, а метол Notify достаточно вызвать а когда баланс счета вновь станет поло жительным, можно его вызвать еще раз. Чтобы реализовать такой сценарий, следу ет разорвать связь между методом Notify и событием после перво го вызова, и восстановить ее, когда баланс счета станет положительным.

Методика удаления связи между обработчиком и событием похожа на методику создания такой связи. В Visual Basic. NET для отключения обработчика события от делегата применяют ключевое слово Remove указывая адрес обработчика с помощью оператора AddressOf. В Visual C# для динамического отключения события от его обработчика служит оператор Этот оператор требует указать ссылку на экземпляр делегата с соответствующей сигнатурой и метод, который необходимо отключить от события. Ниже показан пример отключения метода Display Results от события Account. Calculation Complete:

Visual AddressOf Visual C# -= new Резюме • События — это члены классов, позволяющие им обмениваться сведениями о важных событиях. Экземпляр класса может генерировать событие — член этого класса, чтобы уведомить другие компоненты приложения. Событие обрабаты вается методами, зарегистрированными как обработчики этого события. Обра ботчики выполняются каждый раз, когда генерируется событие.

• Работу событий обеспечивают делегаты. При объявлении события в Visual Basic достаточно указать само событие, а в Visual C# дополнительно требуется указать подходящий делегат, В Visual Basic события генерируют при помо оператора а в Visual C# для этого необходимо обратиться к собы тию по имени. В Visual Basic обработчики событий не способны возвра щать значение, а в Visual C# — могут.

• Метод, обрабатывающий событие, называется его обработчиком. Чтобы про граммно установить связь между обработчиком и событием, которое он обраба тывает, воспользуйтесь экземпляром соответствующего делегата. В Visual Basic для этого используют ключевое слово AddHandler для получения ссылки на метод — оператор AddressOf). В C# события связывают с делегатами при помощи оператора +=. В Visual Basic такую связь можно создать дек ларативно посредством конструкции Handles.

• У события бывает несколько обработчиков;

и наоборот, один обработчик спосо бен обрабатывать несколько событий. Обработчики событий можно динамичес ки подключать и отключать во время выполнения.

Практические Практикум 3. Добавление компонентов и реализация членов Вы создадите класс Doughnut Machine, аппарат по изго товлению пончиков для виртуальной фабрики, речь о которой шла в прак тикуме главы. Новый класс должен по графику создавать эк земпляры класса Doughnut, обновляя форму интерфейса при помощи со бытий. Решение задач этого практикума хранится в каталоге lution на прилагаемом к книге компакт-диске.

Прежде всего Для выполнения задач практикума вам понадобятся результаты практикума главы 2;

можно готовым решением, загрузив его с ком пакт-диска.

Продолжительность практикума - около 45 минут.

Упражнение Создание компонента DoughnutMachine Сейчас вы создадите представляющий аппарат для ства пончиков. Этот класс создает экземпляры класса Doughnut и управ ляет ими, а также открывает доступ к набору объектов, представляющих разные виды пончиков. У него также будут события, уведомляющие ком понент-контейнер о том, что пончик готов.

Создание компонента DoughnutMachine В меню Project выберите команду Add Component — откроется окно Add New Item. Назовите новый компонент или в соответствии с используемым языком программирования и щелкните — ком понент будет открыт в окне дизайнера.

2. На панели Toolbox перейдите на вкладку Windows Forms и дважды компонент Timer — этот компонент Timer появится в окне дизайнера.

3. В окне Solution Explorer щелкните правой кнопкой объект DoughnutMachine и выберите View Code.

4. Добавьте к компоненту DoughnutMachine перечисление, представляющее различ ные сорта пончиков. Оно выглядит примерно так:

Visual Basic Public Glazed Sugar Chocolate Custard Grape PlainCake SugarCake End Visual public DoughnutType i Glazed, Sugar.

Chocolate, ChocolateCake.

Custard, Grape, Lemon, PlainCake, SugarCake 5. Добавьте к созданному классу свойство, представляющее сорт пончика, кото рый он «печет» в данный момент. Для этого объявите в нем закрытую перемен ную для хранения значения этого свойства. Новое свойство класса будет щать значение перечислимого типа DoughnutType. Вот код этого свойства:

Visual Basic Private mFlavor As DoughnutType Public Property Flavor{) As DoughnutType Get Return mFlavor End Get Set Value As DoughnutType) mFlavor - Value End Set End Property Visual C# DoughnutType mFlavor;

public DoughnutType Flavor get return mFlavor;

set 6. Объявите внутри класса Doughnut Machine класс Doughnut, который будет пред ставлять пончик. У него должны быть свойства flavor (сорт пончика), price (его цена), а также свойство, доступное только для чтения, — для хранения времени изготовления пончика. Поскольку единственное место, где разрешается >стано вить свойство, только для чтения, — это необходимо написать для класса Doughnut конструктор, в это свойство теку время на момент создания экземпляра пончика. Код класса может та ким:

Basic Public Class Doughnut Это переменные для хранения значений свойств.

Private As Цена по умолчанию, Private As Single -. Private Readonly mTirneOfCreation As Это класса, Public Property As DoughnutType Get Returr End Get Set(ByVal Value As DoughnutType) - Value End Set Property Public Property As Single Get Return End Get Value As Single) = Value End Set End Property Public Readonly Property As Date Get Return Get End Property Это котором устанавливается значение ' свойства Public Sub Flavor As DoughnutType) - это свойство класса возвращающее текущее время.

Date. Now mFlavor = Flavor End Sub End Class [2 Типы и члены C# public class Doughnut { // Это переменные для хранения значений свойств.

private // Цена по умолчанию.

private float private readonly // Это свойства класса, public DoughnutType Flavor { get { return set { value;

} } public float Price { get { Price;

} set { mPrice - value;

} } public TimeOfCreation { get !

return // Это котором значение public Flavor) { // - это свойство класса // текущее время = System. DateTime. Now;

= Flavor;

Практические 7. Объявите в классе закрытый набор и свойство по умолчанию (в Visual Basic в Visual C# его нужно заменить индексатором), открываю щее доступ к элементам набора. Созданный набор хранит экземпляры класса Doughnut, созданные объектом Doughnut Machine, Вот код этого свойства:

Visual Basic Private As New Public Default Property As Integer) As Doughnut Get Return Doughnut) End Get Set (Value As = Value End Set End Property Visual C# rnDoughnuts = new Doughnut Index] { get :

} set i mDoughnuts[Index] = value;

8. Добавьте к классу открытое событие. Оно сгенерируется к моменту го товности очередного пончика (то есть когда будет создан представляющий его объект). В Visual C# следует также объявить открытый делегат, Visual Basic Public Event Visual public delegate void public event DoughnutComplete;

9. При помощи раскрывающегося списка в окне редактора кода (Visual Basic NET) или кнопки Events в окне дизайнера (Visual C#) добавьте обработчик события (см. код ниже), который создает новые объекты Doughnut, добавляет их к набору и генерирует событие DoughnutComplete.

Visual Basic Private Sub sender As Object, e As System, EventArgs) Handles Din As New RaiseEvent End Sub Visual void 10. Создайте два свойства, доступных только для записи: и Interval с типами и соответственно — они потребуются для установки внутренних свойств таймера. Вот код этих свойств:

Visual Basic Public Property EnabledC) As Boolean Value As Boolean) = Value End Set End Property Public WriteQnly Property As Integer Set(ByVal Value As Integer) - Value End Set End Visual C# - value;

} } int Interval set Interval = value;

:

!

Добавьте к классу метод, настраивающий виртуальный аппа рат, чтобы тот «пек» нужный сорт пончиков через заданные интервалы, и вклю этот аппарат. Этот метод должен принимать в качестве объект, сорт пончика Вот этот метод:

Visual Basic Public Sub As DoughnutType) Flavor dFlavor Select Case dFlavor Case Interval = Case Interval Case Interval = Case Interval = Case Interval Case Interval = Case Interval = Case Interval Case Interval End Select Enabled End Sub Visual public void dFlavor) Flavor = dFlavor;

{ Interval = 15000;

break;

case Interval = 12000;

break;

case Interval = 10000;

break;

case Interval 10000;

break;

case Interval 10000;

break;

case Interval = 5000;

break;

case Interval = 5000;

break;

case Interval = 8000;

break;

case Interval 6000;

break;

} Enabled = } Упражнение 2. Подключение класса к пользовательскому интерфейсу Сейчас вы добавите к классу код для создания экземпляра класса DoughnutMachine, пончики для виртуального магазина, а также код для выбора сорта пончиков и метод, обрабатывающий событие генерируемое компонентом DoughnutMachine. Наконец, вы добавите метод, останавливающий производство пончиков.

Объявите на уровне класса переменную, экземпляр компонен та DoughnutMachine:

Basic Private As DoughnutMachine Visual private DoughnutMachine myDoughnutMachine;

2. Напишите обработчик который создает экземпляр са DoughnutMachine и помещает его в переменную myDoughnutMachine. Вот при мерный код такого обработчика Visual Basic Private Sub sender As e As System. Handles myDoughnutMachine = New End Sub Практические C# private void sender. e) = new } 3. Объявите закрытые переменные для учета количества пончиков:

Visual Basic Private mRaisedGlazed As Integer Private As Integer Private mRaisedChocolate As Integer Private As Integer Private mCakeChocolate As Integer Private mCakeSugar As Integer Private As Integer Private mFilledGrape As Integer Private As Visual C# private int mRaisedGlazed;

private int mRaisedSugar;

private int mRaisedChocolate;

private private int mCakeChocolate;

private int mCakeSugar;

private int private int mFilledGrape;

private mFilledCustard;

4. Создайте для элемента Make из меню Doughnuts вложенные элементы Raised, Cake и Filled, присвоив им внутренние имена и соответственно. Для Raised создайте вложенные элементы Glazed, Sugar и Chocolate, задав для них имена mnuRaisedGlazed, и mnu Raised Chocolate. Вид готового меню в окне дизайнера показан на рис.

5. Добавьте к обработчику события Click элемента меню код, вы метод с параметром, определяющим сорт пончика. Этот код также должен устанавливать свойство Checked элемента меню mnuRaisedGlazed в true, а аналогичные свойства пунктов и — в false. Вот этот код:

Visual Basic Private Sub sender As e As Handles = - False = False private void sender, EventArgs e) { - true;

- false;

= Glazed);

Напишите аналогичные методы для элементов меню Raised Sugar и mnuRai sedChocolate.

I The Factory Help Price Рис. 3-1. Вид интерфейса с меню 6. Создайте метод, обрабатывающий событие которое генериру ет объект Обработчик этого события должен увеличить на переменную для учета готовых пончиков данного сорта и записать ее текущее значение а соответствующее текстовое поле. Вот пример реализации обработчика:

Visual Basic Private Sub Select Case Case mRaisedGlazed = Case += = Case += - roRaisedChocolate.ToString Select End Sub Visual void { switch Flavor) { case ++;

= break;

case ++;

break;

case ++;

7. Добавьте к обработчику события следующий код, связывающий об работчик события Doughnut созданный ранее, с событием Doughnut Complete:

Visual Basic AddressOf Visual += new 8. Добавьте к меню Doughnuts элемент, назовите его &Stop, присвойте ему реннее имя и напишите обработчик события Click для этого пункта меню, устанавливающий свойство Enabled my Doughnut Machine Вот примерный код этого обработчика:

Visual Basic Private Sub sender As e As System. EventArgs) Handles Click Enabled = False End Sub Visual C# private sender, e) { Enabled = false;

} 9. Скомпонуйте и сохраните решение.

10. Нажмите F5, чтобы запустить приложение и проверить, как оно работает.

И. В меню Doughnuts выберите элемент затем Sugar. Убедитесь, что элемент Sugar помечен Каждые восемь секунд значение текстового поля Raised Sugar должно увеличиваться на единицу. Выполните те же самые действия в меню Glazed — соответствующее текстовое поле будет увеличиваться каждые секунд;

а период обновления поля, сорту Chocolate, составит секунд.

12. В меню Doughnuts выберите команду Stop, чтоб закончить «выпечку» пончиков.

Закрепление материала Приведенные ниже вопросы помогут вам лучше усвоить основные темы данной главы. Если вы не сумеете ответить на вопрос, повторите матери ал соответствующего занятия. Ответы для самопроверки — в приложении «Вопросы и ответы» в конце книги.

Объясните, в каких случаях преобразование типов выполняется неяв но, а в каких — явно. В чем опасность явного преобразования типов?

2. Почему вместо значений лучше использовать в коде перечисления и константы?

3. Кратко опишите сходства и различия между массивами и наборами.

4. Чем свойства отличаются от полей? Почему для представления досту па к открытым данным лучше применять а не 5. Объясните, что такое делегат, и расскажите, как он работает.

программирование и полиморфизм Занятие Введение в объектно-ориентированное программирование Занятие 2. Перегрузка членов Занятие 3. Реализация полиморфизма через интерфейсы Занятие 4. полиморфизма через наследование В этой главе Эта посвящена основам объектно-ориентированного (ООП). Вы научитесь создавать перегруженные методы и применять принцип по лиморфизма через интерфейсы и наследование, Прежде всего Для материалов этой главы необходимо знать материал глав 2 и 3, Глава Занятие Введение в объектно ориентированное программирование Программирование в основано на объектах. Объект — это про граммная конструкция, инкапсулирующая набор логически связанных данных и методов. Объекты являются автономными элементами, они предоставляют некото рую другим компонентам среды приложения, изолируя от них свое внутреннее устройство. Объекты создаются на основе шаблонов, называемых классами. Библиотека базовых классов предоставляет набор классов, кото рые можно применять для создания объектов в собственных приложениях. Кроме того, среда разработки Visual Studio позволяет создавать собственные классы для своих программ. На этом занятии основные понятия ООП.

Изучив материал этого вы сможете:

описать члены объекта;

рассказать о различиях между объектами и классами;

определение понятию определение понятиям «абстрагирование», «инкапсуляция» и занятия - около члены и абстрагирование Объект — это программная конструкция, некоторую сущность, В нашей повседневной жизни сущностями, или объектами, можно считать автомоби ли, велосипеды, настольные компьютеры и т.д. Каждый объект обладает определен ной функциональностью и свойствами. В приложении объектом может быть фор ма, элемент управления, такой, как кнопка, соединение с базой в общем, любой элемент. Объект представляет собой завершенную едини цу, которая содержит все данные и предоставляет всю необхо димую для решения задачи, для которой он предназначен. Представление объектов реального мира при помощи программных объектов (abstraction).

Классы как шаблоны объектов При обсуждении классов в главе 1 говорилось, что они представляют собой пользо вательские ссылочные типы. Можно сказать, что классы — это объектов.

Они все члены объекта к его поведение, а также устанавливают перво начальные значения для данных объекта, если это необходимо. При создании эк земпляра класса в памяти создается копия этого класса. Созданный таким образом экземпляр класса называют объектом. Экземпляр класса можно создать посред ством ключевого слова New (new), например, так:

Basic Объявить переменную типа Widget:

Dim as Widget Создать экземпляр Widget и записать его в переменную myWidget = New C# переменную типа Widget // Создать экземпляр объекта Widget // и его в переменную myWidget myWidget = new Widget();

При создании экземпляра класса копия данных, определяемых этим классом, записывается в память и присваивается переменной ссылочного типа, Экземпляры класса не зависят друг от друга и являются отдельными программными циями, Как правило, разрешается создавать произвольное число копий ко торые могут одновременно. Давайте продолжим параллель с реаль ным миром: если считать автомобиль объектом, чертежи автомобиля представляют собой класс объекта По чертежу вы сделаете сколько угодно автомо билей. Если один из автомобилей будет собран не так, как все, это никак не повли яет на остальные.

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

Вернемся к примеру с объектом Автомобиль. Его свойства и поля и т.д. представляют данные, описывающие состояние объекта, а также методы, например или Методы формируют поведение объекта. Событие представляет собой уведомление о важных происшествиях. Для объекта Автомобиль необходимо, чтобы объект Двигатель уведомлял его о событии Перегрев, а взаимодействие с объектом Дерево должно вызвать событие Столкновение.

Объектные модели У простых объектов бывает несколько свойств, методов и одно-два события, сложным объектам требуется больше свойств и методов и даже другие (дочерние) объекты. Сложные объекты способны хранить дочерние объекты и открывать к ним доступ, как к своим членам. Например, элемент управления поддерживает свойство font, которое представляет собой объект типа Font, Аналогично любой экземпляр класса Form содержит и предоставляет набор в который все элементы управления, размешенные на форме. Иерархия вложенных (дочер объектов, формирующих структуру объекта, определяется его объектной лью (object Объектная модель — это иерархия дочерних объектов главного объекта, к кото рым он предоставляет доступ. Обратимся к нашему примеру с автомобилем, мобиль, который сам по себе является объектом, состоит из ряда дочерних объек тов: объекта Двигатель, четырех объектов Колесо, объекта Трансмиссия Ком и дочерних объектов непосредственно определяет работу объекта Автомо биль. Например, поведение объектов у которых свойство дров дочернего объекта Двигатель равно соответственно 4 и 8, будет различным. В свою очередь у дочерних объектов могут быть собственные дочерние объекты. На пример, объект Двигатель (который является дочерним объектом объекта Автомо может иметь несколько дочерних объектов Инкапсуляция Инкапсуляция представляет собой один из базовых принципов ООП, суть которо го состоит в отделении реализации объекта от его интерфейса. Другими словами, приложение взаимодействует с объектом через его интерфейс, который состоит из открытых свойств и методов. Коль скоро интерфейс объекта остается неизменным, приложение сохраняет способность к взаимодействию с ним, даже если в новой версии объекта его реализация полностью изменится.

Объекты должны взаимодействовать друг с другом только через свои открытые методы и свойства, поэтому объекту требуются все необходимые данные и полный набор методов, необходимых для работы с этими данными. Интерфейс ни в коем случае не должен открывать доступ к внутренним данным объекта, поэтому поля с внутренними данными объекта редко объявляют с модификатором (public).

Вернемся к примеру с объектом Автомобиль, который может взаимодействовать с объектом Водитель через открытый где объявлены методы ред, и Остановиться — их достаточно для взаимодействия объектов Водитель и Автомобиль. У объекта Автомобиль может быть дочерний объект Двига тель, но это безразлично объекту Водитель — ему важно лишь наличие методов, вызывая которые, удается получать значения. Так, можно заме нить объект Двигатель, и взаимодействующий с ним объект Водитель не заметит замены, если она не нарушит корректную работу интерфейса.

Полиморфизм Благодаря полиморфизму, одни и те же открытые интерфейсы удается по-разному реализовать в разных классах. Другими словами, полиморфизм позволяет вызывать методы и свойства объекта независимо от их реализации. объект тель взаимодействует с объектом Автомобиль через одноименный открытый интер фейс. Если другой объект, например Грузовик или под держивает этот открытый интерфейс, объект Водитель сможет взаимодействовать и с ними, невзирая на различия в реализации интерфейса. Основных подходов к ре ализации полиморфизма два: через интерфейсы и через наследование.

Реализация полиморфизма через интерфейсы Интерфейс (interface) — это соглашение, определяющее поведение объекта. Интер фейс определяет список членов класса, но ничего не говорит об их реализации. В объекте допустимо реализовать несколько интерфейсов, а один и тот же интерфейс можно реализовать в разных классах. Любые объекты, в которых реализован некий интерфейс, способны взаимодействовать друг с другом через него. Например, в объекте о котором мы говорим, можно реализовать интерфейс IDrivable (по правилам имена интерфейсов должны начинаться с буквы «I») с методами и Остановиться. Этот же интерфейс удастся реализо вать и в других классах, как Автопогрузчик или Катер. В результате 1 а программирование эти объекты получат возможность взаимодействия с объектом Объект Водитель находится в полом неведении относительно реализации интерфейса, с которым он взаимодействует, ему известен лишь сам интерфейс. Подробнее о реа лизации полиморфизма через интерфейсы рассказывается на занятии 3.

Реализация полиморфизма через наследование Наследование позволяет создавать новые классы на основе при этом в новые классы разрешается включать всю функциональность старых и при необходимости модифицировать их члены. Класс, объявленный на основе другого класса, называется его производным или классом-потомком. У любого класса мо жет быть только один прямой предок — его базовый класс (base class). У ного класса окажется тот же набор членов, что и у но при необходи к производному классу разрешается добавлять дополнительные члены. Можно так же изменить реализацию членов, унаследованную от базового переопреде лив их. Производные классы сохраняют все характеристики своего базового класса и способны взаимодействовать с другими объектами, как экземпляры базового клас са. Например, на основе базового класса Автомобиль можно объявить производный от него класс который, в свою очередь, станет базовым для класса Для каждого производного класса разрешены дополнительные члены, но наряду с ними все производные классы сохранят циональность, определенную в исходном классе Автомобиль в неизменном виде.

Реализация полиморфизма через наследование более подробно на занятии 4.

Резюме • Представление объектов из реального мира при помоши программных конст рукций называется абстрагированием. Программные объекты воспроизводят ха рактеристики объектов из реального мира посредством членов и их • Классы аналогичны объектов. При создании объекта в памяти со здается копия его данных, определенных в классе, и устанавливаются началь ные значения для членов-переменных, Класс можно рассматривать как шаблон, на основе которого допустимо создать сколько угодно объектов этого класса, • Инкапсуляция считается одним из фундаментальных принципов ООП. ОПъект должен содержать все необходимые ему данные и код для манипулирования ими.

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

Полиморфизм позволяет по-разному реализовать один и тот же ин терфейс в разных объектах. В Basic и Visual существуют два ос новных типа реализации полиморфизма:

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

• через наследование. Объекты способны наследовать функциональность от других объектов. Производный класс сохраняет полную реализацию своего базового класса;

с экземплярами производных классов можно обращаться как с экземплярами их базового класса. При необходимости разрешено реализо вать дополнительную функциональность в производных классах.

и * Занятие 2. Перегрузка членов Благодаря перегрузке удается создать несколько членов с одним и тем же именем, но с разной сигнатурой. Перегрузку чаще всего применяют с методами, С# также позволяет перегружать операторы. На этом занятии вы научитесь создавать пере груженные члены классов.

Изучив материал этого занятия, вы сможете:

создавать перегруженные методы;

создавать перегруженные операторы (в С#).

Продолжительность - около 15 минут.

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

Visual Basic public void Display(int DisplayValue) Этот метод прекрасно подходит для решения для которых он предназна чен. Но что, если этому методу следует параметр Или передать в параметре строку вместо целого числа? В Visual Basic первая про блема решается при необязательных параметров, но пользователям С# эта возможность недоступна. Более того, необязательные параметры во второй ситуации, когда метод должен принимать аргументы различных типов.

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

Чаще всего перегрузку применяют с методами, создание перегруженных мето дов поддерживает и Visual Basic и последний позволяет перегружать операторы, обеспечивая поддержку нестандартной функциональности пользовательских типов данных с операторами.

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

Basic Пример перегруженного метода.

Public Sub I As Integer) Следующий метод имеет то же имя, что и предыдущий, но отличается от него Sub S As String) Sub C# Пример перегруженного метода.

public void I) !

} В этом примере определены два метода с одинаковыми именами, но разной сиг натурой и реализацией. При вызове метода Display Message среда про веряет тип переданного аргумента. Если это String, вызывается версия метода, ко торая принимает значение типа String, а если — Integer, вызывается версия метода, принимающая аргументы соответствующего типа.

Чтобы создать перегруженный метод, выполните следующие действия.

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

2. Напишите реализацию для нового метода.

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

Visual C# public struct float float Подобную простую структуру можно использовать в бухгалтерском приложении для учета часов рабочего времени и сверхурочных, но при работе с несколькими экземплярами такой структуры возможны сложности. Представьте, например, что требуется сложить значения двух экземпляров такой структуры. Чтобы решить эту задачу, придется писать новый метод, способный складывать экземпляры этой структуры. Для сложения трех и больше экземпляров потребуется вызвать этот ме тод несколько раз. К счастью, С# позволяет определять поведение оператора при обработке пользовательских типов данных. Например, чтобы получить возможность суммировать структуру из нашего примера, можно создать перегруженную версию оператора добавив к ней необходимую Перегруженные операторы создают с помощью ключевого слова operator, имею щего следующий синтаксис:

Visual C# public static type operator op Здесь должна быть реализация.

где type — это тип, с которым работает оператор, он одновременно является типом значения, возвращаемого оператором;

1 и это аргументы опе ратора. Любой унарный оператор обрабатывает только один аргумент с типом type.

Бинарные операторы требуют два аргумента, минимум один из которых должен быть с типом type. Op — это, собственно, оператор, например и т.д. Перегруженные операторы необходимо объявлять с модификаторами public (чтобы клиенты, с вашим типом данных, смогли получить к нему дос туп) и static. Перегруженный оператор следует объявлять внутри определения поль зовательского типа данных, для работы с которым он предназначен. Мы рассмот рели пример со структурой, но также можно определить перегруженный оператор, способный с классами, — все перегруженные операторы определяются одинаково. Вот пример перегруженного оператора предназначенного для ра боты с созданной выше структурой 2 Перегрузка членов Visual C# struct HoursWorked float float OvertimeHours;

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

public static HoursWorked operator + (HoursWorked a, HoursWorked b) HoursWorked Result = new HoursWorkedO;

- + = + return Result;

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

Ниже показан пример кода, сложение двух экземпляров структуры Hours Visual C# // Этот пример предполагает, что Sunday и Monday содержат // экземпляры структуры HoursWorked, инициализированные соответствующими // значениями.

HoursWorked total HoursWorkedO;

total - Sunday + Monday;

Как и в случае с перегруженными методами, допустимо создавать различные реализации перегруженных операторов при условии, что они отличаются рами, Вернемся к примеру со структурой HoursWorked, Допустим, нам потребова лась возможность прибавлять значения типа Integer к полю с помощью оператора Эту задачу удастся решить, создав еще одну версию перегруженного оператора C# float RegularHours;

float OvertimeHours;

// Это перегруженного определенная в предыдущем примере.

static operator + (HoursWorked a, HoursWorked b) { HoursWorked Result = new HoursWorkedO;

- + = + return Result;

и полиморфизм // Новая версия перегруженного оператора + с новой реализацией.

public static operator + a, int b) { Result = new = + b:

return Result;

Чтобы создать перегруженный оператор с помощью Visual C#, выполните сле дующие действия.

1. Объявите перегруженный оператор внутри определения класса или структуры, для работы с которыми он при помоши ключевого слова operator.

Перегруженные операторы необходимо объявлять с модификаторами и static. Если объявляется бинарный оператор, по крайней мере один из его аргу ментов должен иметь тот же тип, что и возвращаемое значение, 2. Напишите реализацию для оператора.

Резюме • Благодаря перегрузке удается создать несколько методов с одинаковым именем, но разными Перегруженные методы должны отличаться турами, но могут иметь одинаковые уровни доступа и типы возвращаемых зна чений. Перегруженные методы объявляются так же, как и обычные, • В программах на можно определять нестандартные версии операторов, пред назначенные для работы с пользовательскими типами данных. Перегруженные операторы следует объявлять с модификаторами public и static и ключевым сло вом operator.

Занятие 3. Реализация полиморфизма через интерфейсы Интерфейсы определяют поведение класса. Один и тот же интерфейс можно реа в самых разных классах, что позволяет им взаимодействовать друг с дру гом, полиморфизма. На этом занятии вы научитесь объяв лять и реализовывать интерфейсы, а также узнаете, как объекты взаимодействуют через интерфейсы.

Изучив материал этого занятия, вы сможете:

определять интерфейсы;

создавать реализацию интерфейса;

объяснить, каким образом удается полиморфизм через интерфейсы.

Продолжительность - около 30 минут.

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

Интерфейс определяет только члены, реализованные в объекте. В определении интерфейса ничего не говорится о реализации его членов — оно содержит лишь описание типов параметров и возвращаемых значений. Реализация членов, объяв ленных в интерфейсе, целиком и полностью ложится на класс, в котором этот терфейс реализован.

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

Определение интерфейсов Интерфейсы определяются с помощью ключевого слова напри мер, так:

Basic Public Interface End Interface Visual C# interface IDrivable { :

программирование и полиморфизм Глава Этот пример объявляет интерфейс но не определяет ни одного члена этого интерфейса. Методы-члены интерфейса определяют с обычной сигнатурой метода, но без модификаторов доступа, таких, как public, и др. Модификатор доступа, заданный для интерфейса, определяет уровень доступа для всех его чле нов. Таким образом, если интерфейс объявлен с модификатором Public, этот моди фикатор действует для всех его членов. Вот пример определения методов как чле нов интерфейса:

Visual Basic Public Interface IDrivable Sub Speed As SUD Halt() As Integer End Interface Visual C# public interface IDrivable { Speed):

void Halt():

int DistanceTraveled():

Помимо методов, в интерфейсах разрешается определять свойства. На Visual Basic свойства-члены интерфейса необходимо определять с ключевым словом или Only. В определение свойства включает (getter), метод-установщик (setter) или оба этих метода. Определение свойства за вершается указанием типа значения, возвращаемого свойством. Вот пример опре деления свойства:

Visual Basic Public Interface IDrivable Определения остальных опущены.

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

ReadOnly Property As Integer End Visual public IDrivable get;

Чтобы сделать это свойство доступным только для чтения, // здесь метод set.

3 через интерфейсы В отличие от свойств, поля не могут быть членами интерфейсов. Это ет, что классы, взаимодействующие через интерфейсы, не получат доступ к внут ренним данным объектов.

Интерфейсы также определяют события, генерируемые объектами, в которых этот интерфейс реализован. Любой класс, некоторый интерфейс, обя зан предоставлять реализацию для всех событий-членов этого но объекты, взаимодействующие через этот интерфейс, не обязаны обрабатывать все объявленные в нем события. Visual Basic предоставляет тип-делегат по умол чанию для всех событий, а С# требует явно назначать событиям Вот пример определения которое является членом интерфейса:

Visual Basic Public Interface IDrivable Определения остальных членов опущены.

Event sender As Object, e As End Interface Visual public IDrivable { // Определения членов опущены.

event } Чтобы определить интерфейс, объявите его с помощью ключевого слова (Visual Basic) или interface (C#) и добавьте к определению интерфейса сигнатуры его членов — методов, свойств и событий.

Интерфейсы как средство достижения полиморфизма Любой объект, в котором реализован некоторый интерфейс, способен к действию с любым другим объектом, требующим этот интерфейс, например:

Visual Basic Public Sub V As IDrivable) опущена End Sub Visual C# Объявленному здесь методу необходимо, чтобы в его аргументе был реализован интерфейс Следовательно, этому методу можно передать любой объект, где реализован этот интерфейс, попутно этот объект преобразуется в тип соответствующего интерфейса. Объектам, взаимодействующим через реализован ный в них интерфейс, доступны члены этого интерфейса.

и Г Кроме разрешается явно преобразовывать объекты, в которых реализован некоторый интерфейс, к типу этого интерфейса. пример демонстриру ет преобразование объекта Truck к типу интерфейса чтобы это сработало, в объекте Truck необходимо реализовать интерфейс IDrivable);

Visual Basic Dim myTruck As New Dim myVehicle As IDrivable Преобразование объекта myTruck в тип интерфейса IDrivable myVehicle myTruck) Visual C# Truck new Truck();

IDrivable myVehicle;

// Преобразование myTruck в тип интерфейса IDrivable myVehicle интерфейсов Чтобы в программе на Visual Basic реализовать интерфейс в классе или структуре, следует воспользоваться ключевым словом а в Visual C# для этой применяется двоеточие, вот пример:

Visual Basic Public Class Truck Implements IDrivable Реализация опущена End Class Visual C# public class Truck : IDrivable { // Реализация опущена } В классах реализуется несколько интерфейсов. Чтобы объявить такой класс, ука жите все необходимые интерфейсы через как показано ниже.

Visual Basic Public Class Implements IDrivable, ICargoCarrying End Class Visual C# public class Truck IDrivable, IFuelBurning, ICargoCarrying // Реализация опущена Если в классе или структуре реализован некоторый интерфейс, необходимо предоставить реализацию для всех его членов, то же правило действует, если реали несколько интерфейсов.

Реализация членов интерфейса на Visual C# На Visual C# члены интерфейсов, объявленных в классах и структурах, реализуют следующим образом. Для этого определяют член с именем, с и члена интерфейса, причем этот член класса объявляется с тем же уровнем доступа, с которым объявлен интерфейс. Вот пример реализации метода как члена интер фейса:

Visual public interface IDrivable { void Speed);

} public class Truck : IDrivable { public Speed) { // Реализация опущена.

Члены реализованные таким способом, становятся доступны как интерфейсу, так и самому классу. В результате эти члены можно вызывать после преобразования объекта, где интерфейс реализован, в его собственный тип либо в тип этого интерфейса.

Кроме того, допустимо реализовать интерфейс в классе явно. Члены, ванные подобным образом, доступны только после преобразования объекта в тип интерфейса. Чтобы реализовать член интерфейса явно, следует объявить в классе одноименный член, указав полное имя интерфейса. Вот пример явно ного метода являющегося членом интерфейса IDrivable:

C# public class Truck : IDrivable { void Speed) { // опущена Обратите внимание, что у этого члена нет модификатора доступа. Поскольку этот член интерфейса реализован явно, его уровень доступа определяется модифи катором, заданным для интерфейса.

программирование и Чтобы реализовать интерфейс в программе на С#, необходимо выполнить сле дующие действия.

1. Объявите класс с нужным интерфейсом при помощи двоеточия (;

). Так можно указать несколько интерфейсов, разделив их имена запятыми.

2. Напишите реализацию для всех членов интерфейса:

• чтобы член оказался доступен как через класс, так и через интерфейс, объя вите этот член с именем, уровнем доступа и сигнатурой, идентичным тако вым членам интерфейса;

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

Реализация членов интерфейса на Visual Basic В программе на Basic ключевое слово Implements позволяет что данный член класса является члена интерфейса. Сигнатура члена клас са, реализующего член некоторого интерфейса, должна быть идентична сигнатуре реализуемого им члена интерфейса, исключение составляет модификатор Следующий пример демонстрирует реализацию являющегося членом ин терфейса:

Visual Public Interface Sub Speed As Integer) Interface Public Class Truck Implements IDrivable Public Speed As Implements Реализация опущена End Sub End Class Член класса, реализующий член интерфейса, вовсе не обязан иметь то же имя, что и член интерфейса. Например, вполне допустима следующая реализация мето да GoForward из интерфейса Visual Basic Public Sub Speed As Integer) Implements Реализация опущена End Sub Любой вызов метода объявленного в интерфейсе в этом примере разрешается на метод Move из класса, реализующего метод интерфейса.

Кроме того, методу класса, реализующему метод интерфейса, можно назначить уровень доступа, отличный от уровня доступа к интерфейсу. Например, разрешает ся реализовать метод интерфейса, объявленного с уровнем доступа Public, через метод класса, объявленный с уровнем доступа Private. В этом случае при доступе к такому методу через интерфейс действует уровень доступа Public, а при доступе че рез класс — уровень доступа Private.

Занятие 3 Реализация через интерфейсы Чтобы реализовать интерфейс на Visual Basic необходимо выполнить сле действия.

1. Объявите класс с необходимым интерфейсом, указав его при помощи ключево го слова Implements. В классе можно реализовать несколько 2. Воспользуйтесь ключевым словом Implements, чтобы создать реализацию для всех членов интерфейса, которые предполагается реализовать в классе.

Резюме • Интерфейс определяет поведение объекта и описание поддерживае мых им членов, их параметров, а также типов возвращаемых ими значений.

Любой где реализован некоторый интерфейс, способен взаимодейство вать с любым другим объектом, которому необходим этот интерфейс. Интер фейсы реализуются как в классах, так и в структурах;

в тех и других реализовать несколько интерфейсов.

• За членов интерфейса отвечает класс или в которой этот член реализован.

• что в классе или структуре реализован некоторый интерфейс, позво лят ключевое слово (в Visual Basic или двоеточие С#). Класс или структура, реализующая некоторый интерфейс, должна обеспечить реали зацию всех членов, объявленных в этом интерфейсе.

• В С# члены интерфейса реализуют двумя способами:

• члена с именем, сигнатурой и уровнем доступа, идентичным та ковым соответствующего члена интерфейса. Такие члены доступны как че рез имя класса, в котором реализован этот интерфейс, так и через имя интер фейса;

• явной реализацией члена интерфейса с указанием его полного имени. Такие члены доступны только через имя интерфейса.

• В Visual Basic члены интерфейса реализуют посредством членов класса или структур с сигнатурой, идентичной сигнатуре соответствующего члена интер фейса. При этом ключевое слово Implements позволяет увязать член интерфейса с соответствующим членом класса. Имя и уровень доступа члена класса могут отличаться от таковых члена интерфейса.

Занятие 4. Реализация полиморфизма через наследование Наследование позволяет объявить новый класс на основе передав новому классу все члены и существующего класса. Так удается создавать классы, реализующие базовый набор возможностей, а затем использовать их для объявления производных классов для исполнения различных, но связанных функций. На этом занятии вы научитесь применять наследование для создания производных классов на основе базовых, создавать новую реализацию для членов базовых классов, а также объявлять абстрактные базовые классы, Изучив материал этого вы сможете:

расширять возможности базового класса;

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

дать определение понятию абстрактного класса;

создавать абстрактные члены.

Продолжительность занятия - около 60 минут.

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

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

Занятие 4 полиморфизма наследование go Создание производных классов Производные классы объявляют при ключевого слова Inherits (в Visual Basic или двоеточия (в С#), Вот пример объявления класса производ ного от класса Truck:

Visual Basic Public Truck опущена End Class Visual public class PickupTruck : Truck { // Реализация опущена !

У производного класса только один предок (базовый класс), но дополнительно в нем разрешается реализовать один или несколько интерфейсов. Если вы объявля ете производный класс, в котором реализовано несколько интерфейсов, следует сразу после ключевого слова Inherits поместить ключевое слово Implements (Visual Basic либо перечислить все интерфейсы после двоеточия, за именем базового класса (С#), Visual Basic Public Class Inherits PickupTruck опущена End Class Visual public class FourWheelDrivePickupTruck : PickupTruck, Объявив производный класс, можно добавить к нему дополнительные члены, реализующие нестандартные возможности.

Как объявить производный класс * в Basic следует указать базовый класс при помощи ключевого слова • в указать базовый после двоеточия в той же строке.

Создание запечатанных классов Иногда требуются классы, которые не способны играть роль базовых. Например, специализированные классы, предназначенные для использования Объектно-ориентированное программирование и полиморфизм В I V _ _ _ _ _ _ _ _. компонентами вашего приложения. Они не пригодятся другим программистам, поскольку не способны дать своим потомкам никакой полезной функциональнос ти. Такие классы можно пометить ключевым словом (Visual Basic или sealed (C#):

Visual Basic Public Class AClass Реализация опущена End Class Visual public sealed class AClass { // Реализация опущена Наследуемые члену Как говорилось ранее, производный класс обладает всей функциональностью базо вого. В производных классах разрешается не только добавлять новые члены, но и изменять реализацию унаследованных членов для решения поставленных задач.

(override) унаследованные от базового класса, удается изме нять их реализацию;

Visual Basic также позволяет замещать (shadow) члены, унаследованные от базового класса. Их можно предоставляя взамен но вый член с тем же именем, но с совершенно иной сигнатурой, уровнем доступа и даже типом. С# позволяет вам скрывать (hide) члены, унаследованные от базового класса, и реализовать взамен член с идентичным именем и сигнатурой, но отлича ющийся другими характеристиками. Переопределение, замещение и сокрытие чле нов более подробно рассматривается в следующих разделах.

Переопределение членов, унаследованных от базового класса Чтобы изменить реализацию членов базового класса, следует переопределить их.

Этот механизм позволяет заменить член, унаследованный от базового класса, чле ном с тем же именем, но с другой реализацией. Например, класс Автомобиль имеет метод У производного класса реализация этого метода может отличаться. Переопределять разрешено только свойства и ме тоды, унаследованные от базового класса, — переменные и события переопреде лять нельзя.

Для объявления другой реализации члена применяют ключевое слово Overrides (Visual Basic или override (C#). В новой реализации члена сигнатура, тип вращаемого значения и уровень доступа должны совпадать с таковыми переопреде ляемого члена, например:

Visual Этот пример предполагает наличие у базового класса метода Public Class Занятие 4 через Inherits Объявить переопределяемый метод Public Overrides Sub Speed As Integer) Реализация опущена End Sub End Class C# Этот предполагает наличие,// у базового класса метода public class : Саг { public override void Speed) < // Реализация опущена } ;

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

Чтобы член базового класса удалось переопределить, он должен быть помечен ключевым словом Overridable (Visual Basic или virtual (C#), противном слу чае члены считаются фиксированными и их переопределить нельзя. Вот пример объявления метода с помощью ключевого слова Overridable Visual Basic Public Overridable Sub Реализация опущена End Sub Visual public virtual void { // Реализация опущена } Как переопределить член базового класса 1. Убедитесь, что член, который вы пытаетесь переопределить, объявлен с ключе вым словом Overridable (virtual), если это не так, этот член не удастся переопреде лить, поэтому придется заместить (скрыть). Как это сделать, рассказано далее.

2. Напишите новую члена при ключевого слова Overrides (override).

и Глава Замещение членов базового класса в Visual Basic Из раздела вы узнали, как заменить реализацию члена, унаследован ного от базового класса. Можно также полностью скрыть члена базо вого класса, заменив его совершенно новым членом с другим уровнем доступа, сиг натурой или членом другого типа. Этот прием называется замещением (shadowing).

В Visual Basic для замещения применяется ключевое слово Shadows.

Basic Это базовый класс Public Function As Integer) As Реализация End Function End Class Это класс Public Class Inherits MyBaseClass Эта функция метод унаследованный от базового класса.

Обратите внимание, что у нее совершенно доступа и тип возвращаемого значения.

Friend Shadows Function S As As Integer опущена End End Class Сокрытие членов базового в Visual C# Если вы пишете на С#, у вас есть возможность заменить член, унаследованный от базового класса, другим членом с совершенно иной Этот прием назы вается сокрытием (hiding). Тип и сигнатура нового члена должны быть же, что и у замещаемого им скрытого члена, но уровень тип возвращаемого значе ния и могут отличаться. Если имя нового метода совпадает с именем одного из существующих, но сигнатуры этих методов новый метод рас сматривается как перегруженная версия существующего метода, при этом послед ний останется доступным. Чтобы скрыть член, унаследованный от базового класса, необходимо воспользоваться ключевым словом new, например, так:

Visual // Это базовый класс class MyBaseClass class :

{ Эта замещает метод MyMethod из базового // класса. что у нее га хе но уровень доступа и возвращаемого значения.

internal new MyMethod(int I).

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

В некоторых случаях получить доступ к реализации замешенных или скрытых членов базового класса все же удается. Откуда будет вызван член — из класса или из производного — зависит от типа переменной, а не от объекта, как в случае переопределенного члена. Рассмотрим следующий пример:

Visual Basic В этом используются классы MyBaseClass и MylnheritedClass, определенные в примере кода.

Dim X As New Dim Y As MyBaseClass ' X и Y теперь ссылаются на один и тот же ' типы переменных отличаются.

Y = X переменной X - MylnheritedClass, поэтому в следующей строке будет вызван из производного класса.

String") Тип геременной Y - в следующей строке будет вызвана реализация из базового Visual В этом используются классы MyBaseClass MylnheritedClass, // определенные в предыдущем примере кода.

MylnheritedClass X - new MyBaseClass Y;

// X и Y теперь на один и тот же // но типы этих отличаются, программирование и полиморфизм Y = X;

// Тип переменной X поэтому // в следующей строке будет вызван член из производного класса.

// Тип переменной Y -- поэтому в следующей строке // будет вызвана реализация из базового класса.

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

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

Как заместить (скрыть) член базового класса • Visual Basic объявите новый член с ключевым словом Shadows и напишите для него реализацию. У нового члена возможна другая сигнатура, уровень дос тупа и тип возвращаемого значения, это может быть даже член другого типа.

• объявите новый член с ключевым словом new и напишите для него реализа цию. У нового члена должны быть такие же сигнатура и тип, что и у скрытого, но уровень доступа и тип значения могут отличаться.

Получение доступа к членам базового класса При объявлении переопределенных или скрытых членов иногда требуется доступ к реализации данного члена в базовом классе. Его получают через ключевые слова MyBase (Visual Basic или base (C#), предоставляющие ссылку на реализацию члена в базовом классе. Эти ключевые слова позволяют вызывать члены из базово го класса следующим образом:

Visual Basic Этот пример демонстрирует реализации базового класса из переопределенного метода Public Overrides Sub MyBase.

Реализация опущена End Sub C# // Этот пример демонстрирует вызов реализации базового класса // из переопределенного метода MyMethod.

public override void MyMethodO { // Реализация !

Занятие 4 через Защищенные члены С уровнями доступа к членам классов вы познакомились в главе 1: члены, объяв ленные с уровнем доступа Public доступны из любой части приложения, в том числе из внешних классов;

члены с уровнем доступа Friend или internal доступ ны только членам из локальной сборки, но не из внешних сборок;

члены с уровнем Private доступны только в пределах класса и не доступны другим классам, в том числе и производным от класса, в котором объявлен этот член. Остальные два уровня доступа, Protected (protected) и Protected Friend подробно не обсуждались в главе 1.

Области видимости членов классов, объявленных с ключевыми словами Protected (protected) и Private (private), совпадают за исключением того, что в первом случае члены доступны и производным классам. Рассмотрим следующий пример;

Visual ' В базовом классе определены два метода:

с уровнями доступа private и protected.

Public Class BaseClass Метод с уровнем доступа private нельзя вызывать ' из производных Private Sub Реализация опущена End Sub...а метод с уровнем доступа protected из производных классов вызывать можно.

Protected Sub Method2() Реализация опущена End Sub Class ' Класс, производный от BaseClass Public Class InheritedClass Inherits BaseClass Public Sub Такой вызов допустим, поскольку уровень доступа protected ' не запрещает доступ к члену, в BaseClass, ' а этот вызов приведет к ошибке компиляции, поскольку он ' обращается к члену базового класса, объявленному ' с уровнем доступа private.

End Sub End Class Visual // В базовом классе определены два метода:

// с уровнями доступа private и public class BaseClass Глава Метод с уровнем доступа private нельзя вызывать // из производных классов...

private // Реализация опущена // Класс, производный от BaseClass public class InheritedClass : BaseClass { public void { // Такой вызов допустим, поскольку доступа protected // не запрещает доступ к члену, обьявленному в BaseClass, // а этот вызов приведет к компиляции, поскольку он // обращается к члену базового класса, объявленному // с доступа private.

Здесь иллюстрируется различие закрытых и защищенных членов. Метод Demo попытается методы Method! и при помощи ссылки на экземпляр класса (через ключевое слово Me Поскольку оба этих метода определены в базовом классе, возможность их вызова определяется уровнями досту па, с которыми они объявлены. Вызов метода завершается успешно, так как он объявлен с модификатором (protected), а метод объявлен ный с модификатором Private (private), производным классам не доступен.

Уровень доступа Protected Friend (protected internal) представляет собой модификаторов Protected (protected) и Friend (internal). Поэтому член класса, объяв ленный с модификатором Protected Friend (protected internal), доступен членам этого класса и других классов, расположенных в той же сборке с этим классом, а также членам своих производных классов.

Абстрактные классы и члены При создании компонентов иногда требуются классы, которые предоставляют не который набор возможностей, используемых в неизменном виде, в то время как за реализацию остальных членов таких классов отвечают их производные классы. Та кими возможностями обладают абстрактные (abstract) классы, которые способны только выполнять роль базовых классов.

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

Создание абстрактных классов Абстрактные классы объявляют с помощью ключевого слова Must Basic или (в С#), например:

Visual Basic Visual C# Создание абстрактных членов У абстрактного класса могут быть различные члены, как у обычного класса. Их объявляют с ключевым словом — в этом случае в производных классах они реализуются по-разному;

в противном случае реализация члена счита ется фиксированной и в неизменном виде передается всем производным классам.

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

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

Абстрактные члены объявляют при помощи ключевого слова (Visual Basic или

Abstract

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

Basic Public Class Public MustOverride I As As Integer Public Property As String End Class и я V _ _ _ ;

_ _ Visual C# public abstract { public abstract void I);

public abstract public abstract string Color { get;

Обратите внимание, что при определении абстрактного свойства на Visual необходимо объявить метод-получатель, метод-установщик или оба. За реализацию этих методов отвечает производный класс. В Visual Basic предполагается, что свойство доступно для чтения и записи, если не указано ключевое слово Readonly или Наследование от абстрактного класса Классы, производные от абстрактных, если они сами таковыми не долж ны предоставлять реализацию для всех абстрактных членов, объявленных в классе предке, Чтобы предоставить реализацию для абстрактного члена, необходимо пере определить его как член любого другого класса. Ниже показан пример реализации абстрактного класса, объявленного в предыдущем примере:

Visual Basic Public Class Inherits Public Overrides Sub I As Integer) Сюда нужно поместить код этого метода, End Sub Public Overrides Function As Integer ' а сюда - реализацию этого метода.

End Function Public Overrides Property As String Get Необходимо написать реализацию для получателя и установщика свойства Get Set(ByVal Value As String) Сюда нужно поместить код установщика End Set End Property End Class 4 полиморфизма через _ _ _ Visual public class МуСаг : Саг { public override void I) { // Сюда нужно поместить код реализации этого метода, public override int { // а сюда - реализацию этого метода.

} override string Color { get { // Необходимо написать реализацию для получателя // и установщика свойства ;

set { // Сюда нужно поместить код реализации Разрешено также создавать новые абстрактные классы, объявляя их на существующих. В этом случае производный абстрактный класс может (но не обя зан) предоставлять реализацию для абстрактных членов, определенных в базовом классе.

Как объявить абстрактный класс 1. Объявите абстрактный класс при помощи ключевого слова (Visual Basic или abstract (C#).

2. Объявите все необходимые абстрактные члены при помощи ключевых слов (Visual Basic или abstract (C#).

3. Напишите реализацию для неабстрактных членов, которые должны быть в ва шем классе.

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

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

• переопределение членов;

• замещение (Visual Basic или сокрытие (С#) членов.

• Доступ к реализации члена в базовом классе обеспечивается через ключевое сло во Base (Visual Basic или base (C#). Чтобы сделать член, объявленный в базовом доступным для класса, объявите его с модифика тором • Абстрактный класс — это своего рода интерфейс, предоставляющий лишь час тичную реализацию класса или вовсе не ее. Не разрешается создавать экземпляры абстрактных классов, они служат исключительно для объявления производных классов. Чтобы предоставить реализацию для абстракт ного члена, последний необходимо переопределить в производном классе.

Практические рекомендации Практикум 4. Применение производных классов Задача этого практикума — создание производных классов и их ние в приложении Doughnut Factory. Вы создадите класс строго типизи рованного набора путем расширения возможностей базового класса на бора и задействуете в своем приложении. Далее вы объявите на основе класса классы и и внесете в прило жение соответствующие изменения, чтобы оно смогло но вые классы. Решение заданий этого практикума вы найдете в каталоге \Labs\Ch04\Solution на прилагаемом к книге компакт-диске.

Прежде всего Для этого практикума вам потребуются выполненные задания практикума 3, их можно также загрузить с прилагаемого компакт-диска.

Продолжительность - около Упражнение Создание класса строго типизированного набора на основе класса CollectionBase Сейчас вы создадите класс набора, который воспринимает и возвращает исключительно экземпляры класса объявив производный класс на основе класса CollectionBase из Framework. Вы напишете реализа для методов Add и а также для свойства Item, включив в нее код, обеспечивающий добавление к набору и извлечение из него только объектов типа Doughnut. Вы также модифицируете код приложения Doug hnut Factory, чтобы оно могло использовать новый класс набора.

Создание класса строго В меню Project выберите команду Add Class — откроется окно Add New Item.

Назовите класс или и щелкните — откроется окно редактора кола с заготовкой нового класса.

2. Сделайте новый класс потомком System. Collections. добавив к нему следующий код:

Visual Basic Public Class Inherits End Class public class :

{ !

и 3. Создайте метод который будет добавлять элементы к набору. Этот метод должен принимать объекты Doughnut в качестве параметра и вызывать метод Add внутреннего объекта Visual Basic Sub aDoughnut As Sub Visual C# public void aDoughnut) { 4. Напишите доступный только для чтения индексатор (С#) или свойство по умол чанию с именем (Visual Basic), возвращающее объект заданным индексом. Заметьте: элементы объекта List хранятся, как объекты типа Object, поэтому вам потребуется явно преобразовать привести элемент набора к типу Doughnut, прежде чем возвращать его. Это можно сделать так:

Visual Basic Default Public Readonly Property Index As Integer) Get End Get End Property Visual C# public this[int index] { !

return 5. Напишите метод, который будет удалять из набора объект Doughnut. Этот метод должен принимать объект Doughnut, его следует реализовать как оболочку для метода Вот пример:

Visual Basic Public Sub aDoughnut As Проверить, является ли заданный Doughnut членом набора If Then заданный End If End Sub Visual public void Doughnut !

if == { 6. Откройте код класса найдите строку, в которой объявляется закрытая переменная mDoughnuts, и измените ее так, чтобы в ней можно было хранить экземпляр класса DoughnutCollection:

Visual Basic Private As New DoughnutCollection() Visual private DoughnutCollection mDoughnuts = new 7. Измените свойство Doughnuts, чтобы оно получило возможность взаимодейство с новым объектом DoughnutCollection, например, так:

Visual Basic Default Public Property Index As Integer) As Doughnut Get Return End Get Value As Doughnut) End Set End Property Visual public Doughnut this[int Index] { get { return } set { программирование и полиморфизм Упражнение 2. Создание дополнительных типов объектов Doughnut Сейчас вы реализуете дополнительные функции виртуальной машины по производству пончиков и закончите инкапсуляцию функциональности компонента Doughnut Machine, скрыв и добавив метод для его установки. Вы также обновите пользовательский интерфейс приложе ния, чтобы добавить к нему поддержку новых видов пончиков.

Создание дополнительных типов объектов Doughnut Измените уровни доступа свойств Enabled и Public на Protected (protected). Это позволит скрыть эти свойства от внешних классов, инкапсулиро вав соответствующую функциональность в классе Machine.

2. После этото свойство станет недоступным для внешних объектов, по этому придется специальный метод для установки этого свойства:

Visual Basic Public Sub Enabled False End Sub Visual public void Enabled - false:

3. Откройте в окне дизайнера и добавьте к элементу меню Dough вложенное меню с элементами Chocolate, Plain и Sugar. При свойте новым элементам меню имена Cake Chocolate, и keSugar. Готовое меню показано на рис. 4-1.

! Doughnuts ;

Cake Stop Main :

'- '- '• Sugar.. slSale Рис. 4-1. Добавление вложенного меню Cake Doughnuts 4. Добавьте к элементу меню Doughnuts\Make\Filled вложенное меню с элемента ми Lemon, Grape и Custard. Присвойте новым элементам имена и Готовое меню показано на рис. 4-2.

Help Make t Raised Sale Add to Sale ;

Рис. 4-2. вложенного меню Doughnuts код метода Замените код, который сбрасывает выделенные пункты меню кодом, автоматически перебирает все из вестные пункты меню и сбрасывает выделение прежде, чем будет выбран другой пункт. Это сделает код для сброса выделения у девяти пунктов меню более упра вляемым и менее громоздким. Описанный метод реализуется так:

Visual Basic Private sender As e As Handles item As Перебрать все элементы из группы Each In As ' Снять со всех меню из группы Each In = False Next = End Sub Visual C# private void sender, e) и Глава // Перебрать все элементы меню из группы item in < // Снять выделение со всех элементов // меню из группы mnuMake.

= false;

} Checked = true;

} 6. Аналогично внесите изменения в код методов и Добавьте сходные методы, события Click элементов меню, до бавленных в пунктах 3 и 4 этого упражнения, 8. Измените метод чтобы он вызывал метод Stop объек та например:

Visual Basic Private Sub sender As e As Handles End Sub Visual private void sender, System. EventArgs e) { } 9. Добавьте к методу код, который будет вести учет новых типов пончиков и обновлять соответствующие элементы управления тельского интерфейса. Для каждого типа должен быть свой опера тор Case, увеличивающий значение закрытой переменной, которая ет соответствующий тип и отображающий обновленное значение этой переменной в соответствующем поле формы.

10. Сохраните проект и протестируйте его.

Упражнение 3. Реализация метода RemoveStale Сейчас вы напишете метод класса Machine, для проверки наличия пончиков, которые «пролежали» в наборе так долго.

что успели засохнуть. Этот метод должен удалять «черствые» пончики из набора и обновлять соответствующим образом данные, отображаемые пользовательским интерфейсом. Вам придется добавить к пользовательс кому интерфейсу код, который будет вызывать этот ме тод и обновлять форму. А также реализовать структуру, группу пончиков различных видов, — она потребуется для возврата сведе ний об удаленных пончиках.

Создание метода 1. В классе объявите структуру, которая способна представлять группу любого размера, включающую любые виды пончиков. Вот пример реа лизации такой структуры:

Visual Public Structure Public As Integer Public As Integer Public RaisedChocolate As Public CakePlain As Integer Public As Integer Public As Integer Public As Public FilledGrape As Integer Public As Integer Structure Visual C# public struct DoughnutGroup { public int RaisedGlazed;

public int RaisedSugar;

public RaisedChocolate;

public int CakePlain;

public int CakeChocolate;

public int CakeSugar;

public int FilledLemon;

public int FilledGrape;

public int FilledCustard;

} 2. Определите в классе DoughnutMachine проверяющий «срок годности» всех пончиков в наборе. Пончики, пролежавшие на складе слишком долго, следует удалить из набора. Этот метод должен возвращать экземпляр структуры nutGroup, уведомляющий о количестве и видах удаленных пончиков.

Visual Public Function As DoughnutGroup Dim As New Dim Counter As Integer Dim UpperBound As Integer - Dim As For Counter - 0 To UpperBound и полиморфизм = If >= Select Case Case += Case += Case Case += Case Case myGroup. += Case += Case Case += End Select - Counter) End If Next Return myGroup End Function Visual public DoughnutGroup DoughnutGroup myGroup = new int UpperBound;

UpperBound - 1;

myTimeSpan;

for(int Counter = 0;

Counter <= UpperBound;

Counter++) 10) Counter]. Flavor) case ++;

рекомендации break;

case ++;

break;

case ++;

break;

case ++;

break;

case ++;

break;

case ++;

break;

case ++;

break;

case ++;

break;

case ++;

break;

- Counter);

3. Добавьте к форме обработчик события Click элемента Remove Stale, который при удалении пончиков будет вызывать метод объекта Machine и обновлять соответствующие элементы управления интерфейса. Вот пример кода этого метода:

Basic Private Sub sender As e As Handles Dim As aDoughnutGroup = = - mRaisedSugar - aDoughnutGroup. RaisedSugar = = mCakeSugar = Объектно-ориентированное и полиморфизм Я 1? • = - aDoughnutGroup.

= mFilledGrape - - aDoughnutGroup. FilledCustard = = txtchocolateRaised.Text = txtcustardFilled.Text = = = = = End Visual C# private void sender, e) { aDoughnutGroup;

aDoughnutGroup = mRaisedGlazed = mRaisedGlazed mRaisedSugar - mCakePlain = mCakePlain = mCakeSugar mCakeSugar - Lemon - aDoughnutGroup. FilledLemon;

mFilledGrape = mFilledGrape mFilledCustard = txtGlazedRaised.Text txtSugarRaised.Text = txtchocolateRaised.Text = ToStringO;

txtcustardFilled.Text = txtLemonFilled.Text txtChocolateCake.Text = = txtSugarCake.Text = 4. Сохраните проект и протестируйте его.

Практические Закрепление материала Приведенные ниже вопросы помогут вам лучше усвоить основные темы данной главы. Если вы не сумеете ответить на вопрос, повторите матери ал соответствующего занятия. Ответы самопроверки — в приложении «Вопросы и ответы» в книги.

1. Дайте краткое определение концепции инкапсуляции и раскройте ее значение для ООП.

2. Что такое перегрузка и для чего применяется?

3. Вам необходимо создать несколько не связанных между собой клас сов, предоставляющих общий набор методов. используя полиморфизма, сделать предоставляемые этими до ступными другим классам?

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

5. Что такое абстрактные классы и для чего их применяют?

Тестирование и отладка приложений Занятие Использование отладочных инструментов Занятие 2. Применение классов Debug и Trace 3. Создание плана блочного тестирования Занятие 4. Обработка и генерация исключений В этой главе Из этой главы вы узнаете, как пользоваться инструментами для отладки приложе ний, применять классы Trace и Debug для диагностики проблем, при исполнении программ, создавать эффективные планы блочного а также научитесь обрабатывать и генерировать исключения.

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

94 и приложений Глава Занятие Использование отладочных инструментов Полностью избежать ошибок при программировании невозможно, даже професси оналы время от времени допускают ошибки. Ошибки в программах часто называют (bugs), а процесс поиска и этих ошибок — отладкой (debug ging, буквально — «ловля На этом занятии вы познакомитесь с различ ными типами возможных ошибок и с инструментами для их поиска и исправления.

Изучив материал этого занятия, вы сможете:

описать наиболее распространенные типы ошибок;

режим Break и устанавливать точки прерывания;

пошаговое исполнение кода;

рассказать, как работают с отладочными инструментами среды разработки.

- около Основные типы ошибок При написании кода программисты сталкиваются с тремя основными типами оши бок. Синтаксические ошибки (syntax errors) если компилятор не в состо янии переданный ему исходный текст. При попытке выполнить тимое действие во время исполнения программы возникают ошибки периода выпол нения (run-time errors). Наконец, логические ошибки (logical errors) не препятствуют компиляции и исполнению программы, но приводят к неожиданным результатам.

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

Visual Public Sub the Visual public SyntaxErrorO { the Во-первых, здесь пропущена точка между и Show, поэтому лятор не распознает такую ссылку. Во-вторых, отсутствует замыкающий элемент конструкции метода (в Visual Basic это End а в Visual — }). Любая из этих ошибок не позволит компилятору интерпретировать такой код.

1 отладочных инструментов Visual Studio облегчает поиск синтаксических ошибок, автоматически об наруживая их при компоновке проекта и выделяя в исходном тексте подсветкой.

Список обнаруженных ошибок также выводится в окне Task List (рис. 5-1).

- 1 X j В Рис. 5-1. Окно Task List Если дважды щелкнуть описание ошибки в окне Task List, среда разработки не медленно переместит курсор соответствующую строку в окне кода и выделит ошибку подсветкой — обычно этого достаточно, чтобы ее распознать и Чтобы получить дополнительное описание выделенной ошибки, нажмите F1.

Visual Basic автоматически проверяет синтаксис кода по мере его ввода, при этом обнаруженные синтаксические ошибки сразу же выделяются подсветкой и добавляются к списку в окне Task List, таким образом, не обязательно иницииро вать компоновку проекта, чтобы обнаружить синтаксические ошибки. Visual C# также поддерживает автоматическую проверку синтаксиса кода при вводе, но она не столь совершенна, как в Visual Basic.

Как найти и исправить синтаксические ошибки Выполните компоновку проекта — при этом любые синтаксические бу дут обнаружены и добавлены в окно Task List (при использовании Visual Basic это делается автоматически без компоновки проекта).

2. Дважды щелкните ошибку в окне Task List — она будет выделена в окне редак тора кода подсветкой.

3. Исправьте найденную ошибку. Если требуется дополнительная информация, на жмите Ошибки периода выполнения Они возникают при попытке приложения выполнить недопустимую операцию. К этой категории относятся деление на ноль и действия, запрещенные политиками безопасности: попытка их исполнения приводит к генерации исключения При возникновении ошибки периода выполнения генерируется исключение (excep tion), предоставляющее описание ошибки, — специальный класс, который служит для передачи сведений об ошибке другим компонентам приложения. Можно напи сать код, который будет обрабатывать исключения, не допуская остановки исполне ния приложения. Подробнее обработка исключений рассматривается на занятии 4.

Логические ошибки Логическую ошибку констатируют, если приложение корректно компилируется и исполняется, но не выдает ожидаемые результаты. Диагностировать такие ошибки труднее, чем из-за отсутствия указаний на источник ошибки. Причиной логической ошибки могут быть такие, на первый взгляд, незначительные промахи, как неверно поставленная точка в десятичной дроби или лишний ноль:

Тестирование и отладка Глава Visual Basic Public Function As Single) As Single Dim As Single YearlySalary HourlyRate * 52 Return YearlySalary End Function Visual C# public float CalculateSalary(float HourlyRate) ;

float YearlySalary = HourlyRate * 52 * 400;

return YearlySalary;

} Этот метод получает значение ставки почасовой оплаты и вычисляет размер го довой зарплаты, умножая полученное значение на число недель в году и на количе ство рабочих часов в неделю. Ошибка возникает, поскольку значение почасовой оплаты умножается на 400, тогда как в рабочей неделе 40 Компиляция и ис полнение этого метода проходит безошибочно, но результат он возвращает невер ный. Чтобы обнаружить ошибку, необходимо предоставить приложе нию тестовые данные и проанализировать полученные результаты. Подробнее об этом рассказывается на занятии 3. Часто для «отлова» логической ошибки прихо дится анализировать код, строку за строкой. Для этого применяется режим поша гового исполнения кода.

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

* при выборе в меню команды Step Step Over или Step Out, а также при нажа тии соответствующей кнопки на инструментальной панели Debug;

• по достижении строки с активной точкой прерывания при исполнении прог раммы;

• при исполнении оператора Stop:

* при возникновении необработанного исключения.

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

Таблица 5-1. Элементы Элемент меню Быстрая клавиша Описание Windows Открывает доступ к командам, различные отладочные инструменты. Более подробно эти инструменты описаны далее Занятие Таблица (окончание) Элемент меню Быстрая клавиша Запускает приложение в режиме отладки;

Start/Continue F если приложение находится в режиме пошагового исполнения, продолжает исполнение программы Останавливает исполнение программы Break All на текущей строке и переводит ее в режим пошагового исполнения. Чтобы возобновить исполнение, выберите команду Continue Останавливает отладчик и Visual Stop Debugging Studio в режим Design Отключает отладчик от всех Detach и закрывает его, не останавливая исполнения программы Restart Перезапускает приложение Apply Code Changes Применяется только с программами на C/C++, недоступен программ на Visual Basic и Visual Открывает окно Processes Processes Открывает окно Exceptions Exceptions Исполняет следующую строку;

если она Step Into F содержит вызов метода, останавливает исполнение в начале этого метода Исполняет следующую строку;

если Step Over содержит вызов метода, исполняет его и останавливает исполнение на следующей строке метода Исполняет код до конца текущего метода Step Out и останавливается перед следующей исполняемой строкой вызывающего метода Открывает окно QuickWatch QuickWatch Открывает окно Breakpoint New Breakpoint Удаляет из приложения все точки Clear All прерывания все точки прерывания, Disable All Breakpoints не удаляя их Ряд отладочных средств (таблица 5-2) доступен через контекстное меню окна кода, Таблица 5-2. Отладочные средства, доступные через контекстное меню окна кода Элемент меню Описание Insert Breakpoint Вставляет точку прерывания в строку New Breakpoint Открывает окно New Breakpoint;

эквивалент одноименной команды из меню Debug отладка приложений Глава Таблица 5-2. (окончание) Элемент меню Описание Add Watch Добавляет выделенное выражение в окно Watch QuickWatch Открывает окно эквивалент одноименной команды из меню Debug Show Next Statement Выделяет подсветкой оператор, который будет исполнен Run To Cursor Исполняет программу до выделенной строки Set Next Statement Назначает выделенную строку для исполнения (выделенная строка должна быть в текущей процедуре) Наиболее востребованные отладочные средства описаны в следующих разделах.

Step Into Команда Step Into (исполнение с заходом) позволяет анализировать работу програм мы, исполняя ее построчно. При ее выборе исполняется текущая строка кода и ис полнение останавливается. Если следующая строка содержит вызов отлад чик исполняет первую строку этого метода, после чего останавливает программу, позволяя проанализировать состояние приложения с помощью отладочных инст Чтобы воспользоваться командой Step Into, выберите ее из меню Debug, либо щелкните соответствующую кнопку на инструментальной панели Debug, либо на жмите Step Over Команда Step (исполнение без захода) исполняет следующую строку кода, как и Step Into, но если в этой строке будет вызов метода, команда Step Over исполняет его до конца и останавливает исполнение перед следующей строкой текущей про цедуры. Step Over позволяет оставаться на одном и том же уровне кода, не заходя внутрь вложенных методов. Команда удобна, когда не требуется анализировать вло женные методы.

Чтобы воспользоваться Step Over, выберите ее из меню Debug, либо щелкните кнопку на инструментальной панели Debug, либо нажмите F10.

Step Out Команда Step Out (исполнить метод) позволяет исполнить текущую про цедуру до конца. Если она вызвана из другого метода, исполнение останавливается перед оператором, следующим за строкой, откуда была вызвана Чтобы воспользоваться командой Step выберите ее из меню Debug, либо щелкните соответствующую кнопку на инструментальной панели Debug, либо жмите Run To Cursor Команда Run To Cursor позволяет выбрать строку кода и выполнить код при ложения до этой строки. Эта команда позволяет пропустить блоки кода, которые не нужно исполнять построчно, например длинный цикл.

Занятие Как воспользоваться командой Run To Cursor В редакторе исходного текста поместите курсор на строку, до которой следует про должить исполнение. Эта строка должна быть строкой исполняемого кода. Щелк ните правой кнопкой мыши и выберите команду Run To Cursor.

Set Next Statement Команда Set Next Statement позволяет пропускать отдельные участки кода. Вы смо жете назначить оператор, который будет исполнен следующим, при этом ется весь код, расположенный до этого оператора, — этим команда Set Next State ment отличается от Run To Cursor. Используя Set Next Statement, удается пропус тить заведомо ошибочные участки кода, а также повторно исполнять ранее испол ненные строки кода.

Чтобы воспользоваться командой Set Next Statement, перейдите в окно редакто ра кода и поместите курсор в строку, которую следует исполнить (она должна быть внутри процедуры). Затем эту строку правой кноп кой мыши и выберите из контекстного меню команду Set Next Statement, Чтобы исполнить помеченную таким образом строку, воспользуйтесь командой Step Into.

Установка точек прерывания Можно назначать определенные строки кода или задавать условия, при нии которых отладчик непременно остановит исполнение приложения. Такие про цедуры называются установкой точек прерывания (breakpoints), они позволяют ос танавливать исполнение программы в заданном месте или при определенных об стоятельствах. Точки прерывания задаются:

• по функции. Они останавливают исполнение по достижении определенной ки • по адресу в файле. Останавливают исполнение приложения по достижении опре деленного места в файле исходного текста;

• по адресу памяти. Останавливают приложение обращении к определенному адресу памяти;

• по данным. Останавливают приложение при изменении значения заданной пе ременной;

недоступны при использовании Visual Basic и Visual C#.

Точки прерывания первого типа применяются чаще всего, их устанавливают одним из трех способов:

• щелкнув серую область в левой части окна кода напротив нужной строки — в результате точка прерывания устанавливается в этой строке ;

• щелкнув правой кнопкой нужную строку и выбрав из контекстного меню ко манду Breakpoint;

• выбрав команду New Breakpoint из меню Debug или из контекстного меню ре дактора кода и установив соответствующие параметры точки прерывания в окне New Breakpoint.

При установке новой точки прерывания через окно New Breakpoint можно за дать условия, определяющие, будет ли остановлено исполнение приложения по достижении этой точки прерывания. Если щелкнуть кнопку Condition, откроется окно Breakpoint Condition, где предлагается ввести некоторое выражение. В резуль тате точка прерывания активизируется, если при вычислении выражения получит ся true либо при изменении выражения. Кнопка Hit окно Break 200 Тестирование и отладка приложений point Hit Count, где задают значение счетчика, по достижении которого точка пре рывания активизируется, Окно Breakpoints Окно Breakpoints (рис. обеспечивает централизованное управление всеми точ ками прерывания.

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

у • (no to Рис. 5-2. Окно Breakpoints Удаление и отключение точек прерывания Точку прерывания, ставшую ненужной, можно удалить либо отключить, если она потребуется в дальнейшем. Как уже говорилось, для управления точками прерыва ния предназначено окно Breakpoints. Вы также можете удалить или перевести в не активное состояние точку прерывания в редакторе кода.

Чтобы удалить ненужную точку прерывания, щелкните ее на серой панели слева от редактора Чтобы отключить точку прерывания, щелкните ее правой кнопкой мыши в ре дакторе кода и выберите Disable Breakpoint. Таким образом, она будет переведена в неактивное состояние.

Применение отладочных инструментов Visual Studio предоставляет несколько инструментов, позволяющих отслеживать ис полнение программ. Одни из них, такие, как окна Output и Command, доступны в режиме Design, а другие, например окно Locals, видно только при отладке. В этом разделе описаны некоторые окна, наиболее часто используемые при отладке.

Окно Output В окне Output отображаются все данные, которые приложение выводит в команд ной строке в ходе его компиляции и исполнения: операторы Debug к Trace, а также сообщения, которыми приложение уведомляет о загрузке сборок. При отладке при ложения в окне Output, как правило, просматривают уведомления оператора о котором более подробно рассказывается на занятии 2. По умолчанию окно Output видно;

в противном случае его можно вызвать, выбрав из меню команду Windows\Output.

Окна Locals, Autos и Watch Окна Locals, Autos и Watch позволяют отслеживать и редактировать пере менных программы во время ее отладки, что удобно при тестировании процедур путем передачи им различных аргументов.

Окно Locals При исполнении программы в режиме отладки в окне Locals можно отсле живать значения всех переменных текущей В нем отображаются три столбца: Name (с именем переменной), Value (с ее значением) и Туре (тип пере менной). Сложные переменные, например экземпляры классов и структур, показа ны в виде дерева с узлами, раскрывая которые, вы получаете доступ к значениям их членов, При передаче управления от метода к методу содержимое окна Locals ме няется, отображая только локальные переменные. В окне Locals Вы можете изме нять значение переменной. Для этого следует выделить в столбце Value значение нужной переменной и ввести новое значение. Заметьте, что так разрешено только значения строковых и числовых переменных. Модифицировать пе помещая в них ссылки на другие экземпляры класса или струк туры, нельзя, зато можно изменять значения их членов. Измененные в столбце Value подсвечиваются красным цветом.

Чтобы отобразить окно Locals во время отладки приложения, выберите из меню Debug команду Окно Окно Autos напоминает окно но его возможности ограничены. В нем ото бражаются те же столбцы, что и в окне Locals, но в них только перемен ные из текущей и предыдущей строк кода (в Visual C#) либо (в Visual Basic переменные из текущей строки плюс три строки до и после нее. В окне Autos мож но изменять значение переменных так же, как и в Locals.

Чтобы вызывать окно Autos во время отладки приложения, выберите из меню Debug команду Окно Watch В окно Watch можно добавить переменную, чтобы отслеживать, как изменяются ее значения. Переменные не удаляются из окна Watch, даже когда они уходят из обла сти видимости. Как и в и Autos, в окне Watch отображаются столбцы Name, Value и Туре, о переменных;

здесь также разрешается изме нять текущие значения простых переменных путем ввода новых значений в стол бец Value. Visual Studio позволяет открывать до четырех окон Watch, что дает возможность отслеживать одновременно несколько наборов переменных, Диалоговое окно предусмотрено для быстрого расчета значения пе ременной. В столбцах Name, Value и Туре этого окна отображаются сведения толь ко об одной переменной;

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

• Чтобы вызвать окно Watch во время отладки приложения, выберите из меню Debug команду Windows, затем одну из команд:

или Watch4.

• Чтобы вызвать диалоговое окно QuickWatch, щелкните правой кнопкой пере менную в окне редакторе кода и выберите из контекстного меню команду Quick Watch.

и приложений Глава.

• Добавить переменную в окно Watch можно одним из следующих способов:

• щелкните пустую строку в окне Watch и введите в нее имя переменной;

• в редакторе кода щелкните правой кнопкой переменную и из контекстного меню выберите команду Add Watch;

• щелкните переменную в редакторе кода, окнах Autos либо и перета ее в окно Watch;

• в диалоговом окне щелкните кнопку Add Watch.

Окно Command в режиме Immediate Этот режим окна Command применяют при отладке для исполнения процедур, рас чета значений выражений или изменения значений переменных.

Окно Immediate позволяет исполнить любой допустимый оператор, но не разре шает объявлять переменные и объекты. В режиме пошагового исполнения кода можно ввести в окно Command оператор или имя метода так же, как в редакторе кода. Нажав Enter, вы заставите Visual Studio исполнить введенный оператор. За вершив исполнение оператора или метода, приложение вернется в режим пошаго вого исполнения.

Когда приложение находится в режиме пошагового исполнения, значения вы ражений и переменных можно вводить в окно Command напрямую, предваряя их знаком вопроса. Например, таким образом перемножить текущие значения X и Y, получив результат в окне Command:

? X*Y Обратите внимание на использование одинакового синтаксиса для Visual Basic и Visual в окне Command. Скажем, в С# строку не обязательно завершать точкой с запятой. Унифицированный синтаксис позволяет получить значение лю бого свойства, которое в настоящей момент находится в области видимости. На пример, следующая команда ?

выводит текущее свойства Text объекта Оператор присваивания позволяет присвоить существующей переменной новое значение. Так, следующий пример присваивает переменной значение 5:

X Заметьте: эту переменную необходимо объявить заранее.

Чтобы вызвать окно Command, укажите в меню View команду Other Чтобы открыть окно Command в режиме Immediate, щелкните ко манду Другие отладочные окна Дополнительные окна отображают сведения об исполнении программы во время отладки и позволяют управлять пошаговым исполнением кода. Они доступны че рез меню Debug (таблица 5-3).

Таблица 5-3. Дополнительные окна, доступные через меню Название Описание Running Documents Отображает список документов, в исполняемый процесс Таблица 5-3. (окончание) Название Описание Me (Visual Basic / Отображает члены данных проекта, связанные с This (Visual C#) методом Call Stack Отображает имена функций из стека вызовов с типов и значений их параметров Threads Позволяет просматривать потоки отлаживаемой и управлять ими Modules Отображает список используемых программой модулей (DLL- и Memory Отображает содержимое памяти. Применяется для просмотра больших буферов, строк и других данных, которые нельзя отобразить окнах Locals, Autos или Watch Disassembly Показывает код сборки, соответствующий сгенерированным компилятором командам Registers Отображает содержимое регистров. Оставив это окно открытым при пошаговом исполнении программы, вы сможете за изменением значений регистров во время исполнения Резюме • При написании программ возможны три типа ошибок:

Pages:     | 1 | 2 || 4 | 5 |   ...   | 7 |



© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

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