Главная страница

1. Массивы и классы 4 Элементы массива как ссылки на объекты 4


Скачать 309.29 Kb.
Название1. Массивы и классы 4 Элементы массива как ссылки на объекты 4
Дата12.11.2018
Размер309.29 Kb.
Формат файлаpdf
Имя файлаpractice_5.pdf
ТипДокументы
#56244
страница4 из 4
1   2   3   4
6. Иногда имеет смысл (для повышения читаемости кода) объединить два объекта с помощью операции. Например, можно написать оператор наподобие totalTime = myTime + yourTime;, где все три переменных — объекты класса Timelnterval. Для достижения такой функциональности в классы включают операции-члены, которые задают набор команд, исполняющийся при объединении объектов в выражении сданной операцией. Этот процесс называют перегрузкой операции. Вложенные типы — это классы, структуры, перечисления и интерфейсы, определенные в пределах тела класса. Они позволяют скрыть типы, которые используются только в пределах класса. Подобно тому, как вспомогательные методы объявляются закрытыми для уменьшения внешней сложности класса, вложенные типы помогают снизить количество классов, необходимых для сборки программы.
6.2. Переменные-члены Ранее уже рассматривались переменные экземпляра поэтому здесь речь пойдет о статических переменных и их использовании.
6.2.1. Переменные экземпляра Когда создается объект, значения переменных экземпляра являются характерными именно для него. Они остаются таковыми в течение всего времени существования объекта. Этот механизм уже знаком, однако его стоит повторить, чтобы проследить отличие от статических переменных, обсуждаемых в следующем разделе. Обратимся к программе BankSimulation.cs (листинг 5.2, стр. 10 -14). Она состояла из объекта содержащего несколько объектов Account
в массиве accounts.
В классе Account
определена переменная экземпляра balance:

25

class Account
{
private decimal balance;
} Объект Bank может содержать любое количество объектов Account (семь в этом примере. Значение переменной balance любого объекта Account можно изменить (переводя средства на или со счета. В примере были изменены балансы первого и второго счетов (они стали равными Значение balance в остальных объектах Account было нулевым. Продолжая моделирование, можно было бы работать со всеми счетами, получив, таким образом семь балансов: Счет 1: balance составляет 110 000,00p Счет 2: balance составляет 240 000,00p Счет 3: balance составляет 35 000,00p Счет 4: balance составляет 55 000,00p Счет 5: balance составляет 300,00p Счет 6: balance составляет 2 000,00p Счет 7: balance составляет 3 500,00p Объект Bank ссылается на семь объектов Account, каждый из которых содержит свое уникальное значение переменной balance. В следующем разделе рассмотрим важное различие между переменными экземпляра и статическими переменными.
6.2.2. Переменные static Переменные экземпляра используются для хранения данных индивидуального объекта. Как быть, если имеется блок данных, связанный с группой объектов одного класса Вернемся вновь к программе BankSimuIation.cs (листинг 5.2). В ней количество счетов задается вначале и неизменно в течение исполнения программы. Предположим, что этого ограничения нет, те. в программе можно открывать и закрывать счета, следя за общим числом созданных объектов
Account. Такой элемент данных описывает уже не свойство конкретного объекта (как переменная экземпляра balance), а связан с группой объектов класса Account. Воспользуемся переменной экземпляра, totalAccountsCreated:
class Account
{
public uint totalAccountsCreated; // Неэффективно
} При создании нового объекта Account необходимо увеличивать totalAccountsCreated на единицу. Такой подход имеет два недостатка
1. Дублирование данных Значение totalAccountsCreated описывает общий атрибут объектов Account. Поэтому программе требуется лишь одна переменная totalAccountsCreated. Однако объявление totalAccountsCreated, приведенное ранее, создает копию этой переменной в каждом экземпляре объекта Account. Это избыточно. Избыточность состоит в том, что для семи объектов Account существуют семь переменных, содержащих одно и тоже значение (7).
26
Это не только засоряет память, но и запутывает других программистов.
2. Из-за необходимости обновления всех объектов Account код становится неэффективным. В данном подходе при создании нового объекта объект Bank должен обновлять (прибавляя единицу к totalAccountsCreated) все объекты Account. Это несложно при небольшом количестве счетов, нов банке, где их число достигает сотен тысяч, оператору цикла потребуется обновить огромную коллекцию объектов Account. Как же решить эти проблемы неэффективности Значение totalAccountsCreated нужно хранить лишь водном месте за пределами отдельного объекта, ново взаимосвязи с группой объектов Account . Поскольку имеется только один класс Account, ион определяет атрибуты, общие для всех его объектов он является естественным местом, где следует хранить и обновлять значение totalAccountsCreated. Именно для этого и предназначено ключевое слово
static. Объявление переменной totalAccountsCreated как static
class Account
{
public static uint totalAccountsCreated; // Эффективно
} указывает, что
1. существует только одна копия totalAccountsCreated,
которая принадлежит всему классу
Account, а не отдельным объектам
2. переменная totalAccountsCreated совместно используется всеми объектами Account
3. переменная totalAccountsCreated имеет определенное значение, даже если не создано ни одного объекта Account
4. значение totalAccountsCreated доступно из класса и из любого объекта Account Хотя переменная totalAccountsCreated и не содержится в каждом конкретном экземпляре
Account, она остается доступной и может быть изменена любым объектом этого класса. Ниже приведен фрагмент кода, где демонстрируются различия между переменной экземпляра ac-
countCreationNumber и статической переменной totalAccountsCreated.
class Account
{
private uint accountCreationNumber;
public static uint totalAccountsCreated;
public void accountsCreatedAfterMe()
{
Console.WriteUne("Кол-во счетов, создан-х в течение исполнения программы {0}", totalAccountsCreated - accountCreationNumber); Одинаковый синтаксис
} Доступ к totalAccountsCreated извне объекта Account осуществляется посредством операции уточнения после имени класса (Account):
}
27

class Bank
{
... Account. totalAccountsCreated...
} Такой способ доступа к totalAccountsCreated невозможен, если переменная объявлена как private (и возможен, если она объявлена как public). ПРИМЕЧАНИЕ Для объявления переменной-члена static имеется два спецификатора — public и private. Как правило следуя принципу инкапсуляции, все статические переменные объявляются как private (подобно переменным экземпляра. В целях демонстрации в данном разделе это правило нарушено переменная totalAc-
countsCreated объявлена public. Если статическая переменная-член объявлена private, прочесть или изменить ее значение можно только с помощью стандартных методов, встречавшихся ранее, или методов
static (которые также ассоциированы с классом, а нес его объектами. ПРИМЕЧАНИЕ Статическая переменная-член (наподобие totalAccountsCreated) недоступна при применении операции уточнения к имени отдельного объекта
class Bank
{
Account myAccount = new Account();
...myAccount.totalAccountsCreated... // неверно
} Листинг 5.7 демонстрирует чтение и модификацию переменной-члена
totalAccountsCreated, объявленной public static
(строка 8). Программа
DynamicBankSimulation.cs содержит сокращенные версии трех классов — Account, Bank и
BankSimulation — из программы BankSimulation.cs (листинг 5.2). В отличие от
BankSimulation.cs программа DynamicBankSimulation.cs позволяет открывать и закрывать банковские счета в течение времени исполнения. Программа сохраняет информацию об общем числе созданных счетов (в переменной totalAccountsCreated) и их текущем количестве переменная bigBucksBank).
6.3. Листинг 5.7. Исходный код DynamicBankSimulation.cs.
01: using System; // Прог-ма мод-ния работы в банке доступ и управление несколькими счетами
02: using System.Collections;
03: namespace ConsAppl_DinamicBankSimulation
04: {
05:
06: class Account // Account (счет) - это польз-кий класс Account - это объект (см. файл Mic10_14c387.cs)
07: { // Объект Account (счет) должен хранить след-ю статическую переменную
08: public static uint totalAccountsCreated = 0; // общее количество созданных объектов (счетов)
09:
10: public Account() // Это кон-р Account, те. м-д стем же именем, что и кл-с Account, в кот-м он наход-ся
11: { // Назначение конст-ра - инициализация переменных экземляра класса Account
12: totalAccountsCreated++;
13: }
14: } // окончание - class Account
15
:
/******************************************************/
28

16
17
18
19
20
21 22 23 24 25
26
27 28 29 30 31 32
33
34 35 36 37 38 39 40 41 42 43 44 45 46
47
48 49 50 51
52
53
54
55
56
57
58
59 60 61 62 63 64
c l a s s B a n k // класс Bank содержит коллекцию счетов. Все м-ды класса Bank предн-ны для изме-ния или чтения
{ // инфор-ции одного счета или всей кол-ции счетов и, след-но, зависят от м-дов кл-са Account
private ArrayList accounts; // классу Bank треб-ся только одна перем-я экз-ра - мас-в счетов accounts
public Bank() // Конст-р Bank - создает новые объекты Account, кот-ми класс Bank будет управлять
{ Поздравляем Вы создали новый банк accounts = new ArrayList();
}
public void AddNewAccount() // Добавьте Новый Счет
{ accounts.Add(new Account()); // Добавить новый счет
PrintStatistics(); // строки 47- 51
}
public void RemoveFirstAccount() // Первый Счет Удаления
{
if (accounts.Count > 0)
{ accounts. RemoveAt(0); Счет удален
PrintStatistics(); // строки 47- 51
}
else
{ Извините, нет больше текущих счетов
}
}
public void PrintStatistics()
{
Console. Номер текущего счета " + accounts.Count + Количество новых созданных счетов " + Account.totalAccountsCreated);
}
} // окончание - class Bank
/********************************************/
class DynamicBankSimulation // класс Динамическое Моделирование Банка
{ // классу BankSimulation требуется только одна перем-я экз-ра - объект Bank
private static Bank bigBucksBank;
public static void Main()
{
string command; bigBucksBank = new Bank(); // Создание нового объекта Bank
do
{
29

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88:
89
90 91 92 93 94 95 96
97
98
PrintMenu(); command = Console.ReadLine().ToUpper();
switch(command)
{
case "A":
bigBucksBank.AddNewAccount(); // строки 26- 31
break;
case "E":
Console.WriteLine("Bye Bye!");
break;
case "R":
bigBucksBank.RemoveFirstAccount(); // строки 33 - 45
break;
case "P":
bigBucksBank.PrintStatistics(); // строки 47- 51
break;
default:
Console.WriteLine(" неправильный выбор
break;
}
} while (command != "E");
Console.ReadLine();
}
private static void PrintMenu()
{
Сопзоіе^гіїеипе("\пЧто Вы желаете сделать?\п" +
"A) Добавить новый счет\п" +
"R) Удалить счет\п" +
"P) Печать статистики\п" +
"E) Сессия окончена\п");
}
} // Окончание класса DynamicBankSimulation
}
6.4. Результаты работы программы Поздравляем Вы создали новый банк Что Вы желаете сделать А Добавить новый счет
R) Удалить счет Р Печать статистики Е Сессия окончена р <Еп1ег> Номер текущего счета 0 Количество новых созданных счетов 0 Что Вы желаете сделать
30

a Добавить новый счет Номер текущего счета 1 Количество новых созданных счетов 1 Что Вы желаете сделать
a Добавить новый счет Номер текущего счета 2 Количество новых созданных счетов 2 Что Вы желаете сделать
r Счет удален Номер текущего счета 1 Количество новых созданных счетов 2 Что Вы желаете сделать
e
Bye Bye! Примечание Для экономии места меню приведено только один раза затем заменено троеточием (...). Для сокращения кода класс Account
не содержит переменной экземпляра balance. В строке 8 переменная-член totalAccountsCreated типа uint объявлена как static. При запуске программы она инициализируется нулем, что позволяет обращаться к ней прежде, чем созданы какие-либо объекты класса Account. Это демонстрируется командой P вначале вывода примера пользователь узнает, что на данный момент открыто и существует ноль счетов. Команда Р посредством разделав строках 78—80 вызывает метод PrintStatistics (строки
47—51) объекта bigBucksBank класса Bank. Обращение к переменной totalAccountsCreated производится в строке 50 с помощью операции уточнения Account.totalAccountsCreated. Значение переменной totalAccountsCreated можно прочесть и изменить из объекта Ac-
count также, как значение любой стандартной переменной экземпляра. Сказанное демонстрируется конструктором Account (строки 10-13). Напомним, что конструктор вызывается при создании каждого нового объекта. В данном случае он увеличивает значение переменной totalAc-
countsCreated на единицу (строка 12). Стандартный массив С представленный в листинге 5.2, после создания имеет фиксированную, неизменяемую длину. Здесь же требуется конструкция, подобная массиву (содержащая коллекцию объектов, но способная при необходимости увеличиваться или уменьшаться. Такой функциональностью обладает класс Arraylist, содержащийся в пространстве имен System.Collections.NET Framework. Его полное имя System.Collections.ArrayList, но благодаря декларации в строке 2 (using System.Collections;), можно применять сокращение
ArrayList (в строках 18 и 23). Подобно классами содержит большой набор встроенных методов. Однако в данной программе используются два собственных
31
метода Add (строка 28) и RemoveAt (строка 37), а также свойство Count (строки 35 и 49). Когда в конструкторе объекта Bank (строка 23) создается экземпляр accounts (объявленный в строке
18), его длина равна 0. Объект ArrayList может хранить любые объекты, поэтому его базовый тип (как в случае массива) определять ненужно. Для добавления в список нового объекта Account применяется метод Add, аргументом которого является ссылка на объект (см. строку 28). Данный метод до- редь). Метод РетоуеД1 удаляет объект, индекс которого задан в аргументе (строка 37).
бавляет объект вконец существующего списка (аналогично тому, как клиенты становятся в оче-
Свойство Count содержит текущее число объектов в списке ArrayList. Между Count и totalAccountsCreated существует смысловое различие
totalAccountsCreated подсчитывает сколько разв программе создавался новый счет a
Count следит за текущим количеством объектов в списке accounts. Таким образом, значение
Count увеличивается, когда объекты добавляются, и уменьшается при их удалении
totalAccountsCreated увеличивается в первом случае ноне уменьшается во втором.

a
32
Контрольные вопросы
1. В каждом из трех модулей компиляции находится следующее определение пространств имен Модуль компиляции 1: namespace MyCompany
{
public class Bicycle
{
}
} Модуль компиляции 2: namespace MyCompany.Design
{
public class Drawer
{
}
} Модуль компиляции З namespace MyCompany.Design.Tools
{
public class Cutter
{
}
} Все модули необходимо собрать в одну сборку. Вместо трех модулей компиляции нужно создать один с такой же структурой пространств имен, как и объединяемые. Для решения задачи используйте следующее определение вложенных пространств имен в С
namespace <Внешнее_пространство_имен>
{
namespace <Внутреннее_пространство_имен>
{ и т.д.
2. Вы создали два исходных файла Bicycle.cs
и Person.cs.
Их нужно скомпилировать в сборку healthlib.dll.
При компиляции необходимы ссылки на две сборки — mathlib.dll и anat-
omy.dll. Напишите команду компилятора, выполняющую эти действия Для чего применяется утилита ildasm?
33
Задание по самостоятельной работе #1 Напишите базовый код программы автомобильной игры. Программа должна включать класс Саг со следующими элементами
1. переменная экземпляра position типа int
2. метод с заголовком public void MoveForward(int distance), который добавляет расстояние distance к переменной экземпляра position
3. метод с заголовком public void Reverse(int distance), который вычитает расстояние distance из позиции метод GetPosition, возвращающий величину position в точку вызова Кроме того, программа должна содержать класс CarGame, который (используя массив) содержит 5 объектов типа Саг Этот класс должен позволять перемещать каждый автомобиль (впереди назад) и возвращать положение каждого из автомобилей (заданного посредством индекса массива. Программа также должна содержать класс CarGameTester, содержащий метод Main. Напишите небольшую тестовую программу (она включает классы Сап CarGame и CarGameTester) и убедитесь, что оба класса (Сап CarGame) функционируют правильно. Задание по самостоятельной работе #2
1. Выполните упражнение (аналогично упр-нию #3 к Практ-му занятию №4, стр. 42) для исходного файла BankSimulation.cs из листинга 5.2. Создайте по одному модулю компиляции для каждого класса Account и Bank и разместите их в подходящей иерархической структуре пространств имен. Соберите эти части в одну сборку. Создайте исходный файл для программы моделирования банка, использующий пространства имени классы сборки. Функциональные возможности данной программы должны быть идентичны возможностям оригинальной (из листинга
1   2   3   4


написать администратору сайта