Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Задания по ООП.pdf
Скачиваний:
16
Добавлен:
25.03.2016
Размер:
1.65 Mб
Скачать

Result_TB.Text = "\"" + Spisok_LB.SelectedItem + "\" > \"" + E + "\" = " + Result;

}

else

MessageBox.Show("Не выбран элемент", "Ошибка");

}

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

Рисунок 2 – Внешний вид и пример работы программы, реализующей перегрузку операторов

1.3 Использование делегатов

Задание2: создать класс с заданными параметрами и реализовать работу с ним.

Описание параметров задания

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

2Полные требования к выполнению задания приведены в общей части раздела

2.3

20

делегаты:

1.делегат для обратного вызова, позволяющий вывести описание выполненного действия;

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

«1»;

обязательные поля класса:

1.идентификатор, int, уникальный;

2.первое число, int;

3.второе число, int, ≠0, по умолчанию 1;

4.ссылка на компонент, в котором хранится и отображается элемент;

отображение: «<идентификатор> : <первое число>/<второе число>»;

обязательные методы класса:

1.метод, добавляющий к первому числу переданное значение и вызывающий делегат типа «1» для передачи описания выполненного действия;

2.метод, добавляющий ко второму числу переданное значение и вызывающий делегат типа «1» для передачи описания выполненного действия;

операции, требующие реализации:

1.добавление к первому числу;

2.добавление ко второму числу;

3.удаление добавления к первому числу;

4.удаление добавления ко второму числу;

5.удаление всех операций.

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

Для решения поставленной задачи потребуются компоненты:

Spisok_L класса Label для подписи компонента Spisok_LB;

Spisok_CLB класса CheckedListBox для хранения списка элементов;

AddElement_GB класса GroupBox для визуального выделения компонентов добавления элемента списка;

First_L класса Label для подписи компонента First_TB;

First_TB класса TextBox для ввода первого числа элемента

списка;

Second_L класса Label для подписи компонента Second_TB;

Second_TB класса TextBox для ввода второго числа элемента

списка;

21

AddElement_B класса Button для активизации добавления элемента списка;

DelElement_B класса Button для активизации удаления помеченных элементов списка;

Opeartions_GB класса GroupBox для визуального выделения компонентов назначения операций элементам списка;

AddFirst_B класса Button для активизации назначения помеченным элементам списка операции «Добавление к первому числу»;

AddSecond_B класса Button для активизации назначения помеченным элементам списка операции «Добавление ко второму числу»;

DelFirst_B класса Button для активизации назначения помеченным элементам списка операции «Удалить добавление к первому числу»;

DelSecond_B класса Button для активизации назначения помеченным элементам списка операции «Удалить добавление ко второму числу»;

Clear_B класса Button для активизации назначения помеченным элементам списка операции «Удалить все операции»;

Run_GB класса GroupBox для визуального выделения компонентов выполнения назначенных операций;

Number_L класса Label для подписи компонента Number_TB;

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

Calc_B класса Button для активизации выполнения назначенных операций;

Result_L класса Label для подписи компонента Result_TB;

Result_TB класса TextBox для вывода списка выполненных операций, полученных за счет делегата обратного вызова.

Установим следующие значения свойств компонентов (таблица 4).

Таблица 4 – Значения свойств компонентов для примера выполнения задания по использованию делегатов

Компонент.Свойство

Значение

 

 

Spisok_L.Text

Спи&сок элементов

AddElement_GB.Text

Добавление нового элемента

First_L.Text

П&ервое число добавляемого элемента

Second_L.Text

В&торое число добавляемого элемента

AddElement_B.Text

До&бавить элемент

DelElement_B.Text

У&далить все помеченные элементы

Opeartions_GB.Text

Назначение операций помеченным объектам

AddFirst_B.Text

Добавление к &первому числу

22

AddSecond_B.Text

Добавление ко &второму числу

DelFirst_B.Text

Удалить добавление к &первому числу

DelSecond_B.Text

Удалить добавление ко второму &числу

Clear_B.Text

Уд&алить все операции

Run_GB.Text

Выполнение операций

Number_L.Text

Число для операци&й

Calc_B.Text

В&ыполнить действие

Result_L.Text

Выполненные &операции

Result_TB.Multiline

True

 

 

Result_TB.ReadOnly

True

 

 

Для реализации класса (назовём его Element) потребуется отдельный модуль. Добавим его в программу через меню «Проект → Добавить класс». Также в этом модуле опишем требуемые делегаты. Реализация делегатов и членов класса приведена ниже.

//Делегат обратного вызова, в качестве параметра которого

//передается выводимая строка

public delegate void CalcBack(string s);

//Делегат, позволяющий вызвать методы класса и возвратить

//после выполнения метода требуемую строку

public delegate void CalcDelegate(int n,

CalcBack PrintResult);

class Element

{

private static int _Count; // Счетчик объектов private int _ID, _First, _Second;

//Ссылка на компонент отображения private CheckedListBox _LB;

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

public Element() : this(1, 1, null) { }

public Element(int First, int Second, CheckedListBox LB)

{

_ID = ++_Count; _First = First;

_Second = Second != 0 ? Second : 1; _LB = LB;

}

// Свойства для работы с полями public int First

{

get { return _First; } set

{

_First = value;

23

// Изменение отображения объекта в компоненте if (_LB != null)

_LB.Items[_LB.Items.IndexOf(this)] = this;

}

}

public int Second

{

get { return _Second; } set

{

if (value != 0)

{

_Second = value;

// Изменение отображения объекта в компоненте if (_LB != null)

_LB.Items[_LB.Items.IndexOf(this)] = this;

}

}

}

//Переопределение метода отображения объекта public override string ToString()

{

return _ID + " : " + First + "/" + _Second;

}

//Первый обязательный метод

public void AddFirst(int n, CalcBack PrintResult)

{

//Выполнение операции

_First += n;

//Изменение отображения объекта в компоненте

if (_LB != null) _LB.Items[_LB.Items.IndexOf(this)] = this;

// Вызов делегата для возврата требуемой строки

PrintResult(string.Format(

"Объект №{0}. Добавлено {1} к первому числу", _ID, n));

}

// Второй обязательный метод

public void AddSecond(int n, CalcBack PrintResult)

{

_Second = _Second + n != 0 ? _Second + n : 1; if (_LB != null)

_LB.Items[_LB.Items.IndexOf(this)] = this; PrintResult(string.Format(

"Объект №{0}. Добавлено {1} ко второму числу", _ID, n));

}

}

24

В классе основной формы опишем поле типа CalcDelegate, которое будет хранить список операций, которые необходимо выполнять:

public CalcDelegate Calc = null;

Опишем событие Click кнопки AddElement_B:

private void AddElement_B_Click(object sender, EventArgs e)

{

int c = 0; try

{

int First = Convert.ToInt32(First_TB.Text); c = 1;

int Second = Convert.ToInt32(Second_TB.Text); if (Second == 0)

{

Second_TB.Focus(); throw new Exception(

"Второе число не должно равняться нулю");

}

Spisok_CLB.Items.Add(new Element(First, Second, Spisok_CLB));

}

catch (FormatException)

{

if (c == 0)

{

First_TB.Focus();

MessageBox.Show("Первое число должно быть целым числом", "Требуется исправление");

}

else

{

Second_TB.Focus();

MessageBox.Show("Второе число должно быть целым числом", "Требуется исправление");

}

}

catch (Exception E)

{

MessageBox.Show(E.Message, "Требуется исправление");

}

}

Опишем событие Click кнопки DelElement_B:

private void DelElement_B_Click(object sender, EventArgs e)

{

//Так как при удалении элемента происходит сдвижка всех

//последующих элементов к началу списка, проще осуществлять

25

// перебор элементов с конца списка

for (int i = Spisok_CLB.Items.Count - 1; i >= 0; i--)

// Проверка, помечен ли текущий элемент if (Spisok_CLB.GetItemChecked(i))

Spisok_CLB.Items.RemoveAt(i);

}

Опишем событие Click кнопки AddFirst_B:

private void AddFirst_B_Click(object sender, EventArgs e)

{

for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))

{

// Получение помеченного элемента

Element Item = Spisok_CLB.Items[i] as Element;

//Добавление в поле типа «делегат» ссылки на метод

//помеченного элемента

Calc += Item.AddFirst;

}

}

Опишем событие Click кнопки AddSecond_B:

private void AddSecond_B_Click(object sender, EventArgs e)

{

for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))

{

Element Item = Spisok_CLB.Items[i] as Element; Calc += Item.AddSecond;

}

}

Опишем событие Click кнопки DelFirst_B:

private void DelFirst_B_Click(object sender, EventArgs e)

{

if (Calc != null)

for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))

{

Element Item = Spisok_CLB.Items[i] as Element; int n;

//Так как метод может быть добавлен в поле типа

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

//до тех пор, пока после выполнения операции удаления

//количество добавленных в поле методов не останется

//таким же, как и до удаления

do

{

26

//Запрос текущего количества методов, добавленных в

//поле типа «делегат»

n = Calc.GetInvocationList().Length; Calc -= Item.AddFirst;

}

while (n != Calc.GetInvocationList().Length);

}

}

Опишем событие Click кнопки DelSecond_B:

private void DelSecond_B_Click(object sender, EventArgs e)

{

if (Calc != null)

for (int i = 0; i < Spisok_CLB.Items.Count; i++) if (Spisok_CLB.GetItemChecked(i))

{

Element Item = Spisok_CLB.Items[i] as Element; int n;

do

{

n = Calc.GetInvocationList().Length; Calc -= Item.AddSecond;

}

while (n != Calc.GetInvocationList().Length);

}

}

Опишем событие Click кнопки Clear_B:

private void Clear_B_Click(object sender, EventArgs e)

{

Calc = null;

}

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

private void PrintResult(string s)

{

Result_TB.AppendText(s + Environment.NewLine);

}

Опишем событие Click кнопки Calc_B:

private void Calc_B_Click(object sender, EventArgs e)

{

try

27

{

int Number = Convert.ToInt32(Number_TB.Text); Result_TB.Clear();

//Если операции назначены, то выполняем их if (Calc != null)

Calc(Number, PrintResult); else

//Иначе выводим сообщение

PrintResult("Не назначено ни одной операции");

}

catch (FormatException)

{

Number_TB.Focus();

MessageBox.Show("Число для операции должно быть целым", "Требуется исправление");

}

}

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

Рисунок 3 – Внешний вид и пример работы программы, реализующей использование делегатов

28