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

CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky

.pdf
Скачиваний:
31
Добавлен:
22.03.2016
Размер:
2.08 Mб
Скачать

потребления воды, электроэнергии и т.п. Определить класс Counter, объект которого моделирует работу кольцевого счетчика. В классе декларировать статическое поле maxCount для представления предельного значения, допустимого для показаний счетчиков объектов класса. Текущее показание конкретного счетчика будет представлять целочисленное поле объекта (нестатическое поле класса) с именем count. В классе определить: метод increment() для увеличения на 1

текущего показания счетчика, метод getCount() для считывания текущего показания и метод display() для вывода информации о состоянии и возможностях счетчика.

Один из возможных вариантов определения такого класса (программа

11_04.cs):

// 11_04.cs - класс "кольцевой счетчик" using System;

class Counter // Класс "кольцевой счетчик" { // Закрытые поля:

static int maxCount = 100000; // продельное значение int count; // текущее показание

//Метод - приращение показания: public void increment() {

count += 1;

if (count >= maxCount) count = 0;

}

//Метод для получения текущего показания: public int getCount() { return count; }

//Метод для вывода сведений о счетчике (об объекте): public void display() {

Console.WriteLine("Reading: {0,-8} maxCount: {1,-8}", count, maxCount);

}

}

Вобъявлении полей static int maxCount и int count; модификаторы доступа не использованы, и по умолчанию переменные maxCount и count закрыты для доступа

извне (имеют статус доступа private). Статическое поле maxCount

инициализируется значением 100000 при компиляции. При создании каждого объекта класса инициализируется поле count конкретного объекта. Если

инициализатор переменной поля отсутствует, то, как мы знаем, выполняется ее

инициализация умолчиваемым значением. В нашем примере переменная count при создании объекта инициализируется целочисленным значением 0.

В классе явно определены два нестатических открытых (имеющих статус

доступа public) метода.

Метод с заголовком public void increment()

при каждом обращении к нему увеличивает на 1 значение показания (поля count),

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

Метод с заголовком public void display()

осуществляет вывод сведений о текущем показании счетчика, представляемого

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

Чтобы привести пример создания и использования объектов класса Counter,

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

Возникает вопрос, а как же быть, если в нашем классе Counter нет явного определения конструктора? В языке C# принято, что при отсутствии конструктора в декларации класса, в этот класс компилятор автоматически встраивает открытый конструктор умолчания "конструктор умолчания" , то есть конструктор, при обращении к которому не требуется задавать аргументы. В следующей программе

определяются ссылки с1 и с2 типа Counter и создаются связанные с ними объекты.

К объектам посредством ссылок применяются нестатические методы класса

Counter.

static void Main( ) {

Counter c1 = new Counter( ); // конструктор умолчания Counter c2 = new Counter( );

c1.display( );

Console.WriteLine("c1.ToString( ): " + c1.ToString( )); Console.WriteLine("c1.GetType( ): " + c1.GetType( )); for(int i = 0; i < 150000; i++) {

c1.increment( );

if (i % 10 == 0) c2.increment( );

}

Console.WriteLine("c1.getCount() = " + c1.getCount( )); c2.display( );

}

Для краткости здесь только текст функции Main( ). Предполагается, что и определение класса Counter и функция Main() принадлежат одному пространству имён.

Результаты выполнения программы:

Reading: 0 maxCount: 100000 c1.ToString( ): Counter c1.GetType( ): Counter c1.getCount( ) = 50000

Reading: 15000 maxCount: 100000

В теле функции Main( ) оператор Counter c1 = new Counter(); объявляет переменную с1 – ссылку типа Counter. Выражение с операцией new представляет собой обращение к конструктору умолчания, неявно включенному компилятором в класс Counter. Тем самым создан объект класса Counter и с ним связана ссылка с1.

Аналогично определяется второй объект и связанная с ним ссылка с2.

Оператор с1.display(); – это обращение к нестатическому методу display(),

который вызывается для обработки объекта, связанного со ссылкой с1. В

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

Reading: 0 maxCount: 100000

Вид представления определяет форматная строка метода Console.WriteLine( ),

вызываемого в теле метода display( ). Так как при создании объекта использован конструктор умолчания Counter(), то переменные (поля) объекта получили значения за счет их инициализации (count=0 и maxCount=100000).

Следующие два оператора метода Main( ) иллюстрируют применимость к

объектам введенного программистом-пользователем класса Counter, методов,

унаследованных этим классом от класса object. Как мы уже говорили, класс object

является первичным базовым классом всех классов программ на C#. Применяемые к объектам пользовательского класса Counter методы ToString( ) и GetType( )

позволяют получить имя этого класса.

В цикле с заголовком for (int i = 0; i < 150000; i++) выполняются обращения к

методу incrementM() для двух объектов класса, адресуемых ссылками с1 и с2. Для первого из них выполняется 150000 обращений, для второго в 10 раз меньше.

Метод при каждом обращении увеличивает текущее значение счетчика на 1, но

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

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

возможностей работы с его объектами, отметим, что в функции Main()

используются только открытые методы класса Counter. В объявлениях методов

increment(), getCount() и display() явно использован модификатор public.

Конструктор умолчания Counter() создается компилятором автоматически как открытый. Именно названные четыре метода класса Counter формируют его внешний интерфейс. Обращения к закрытым полям класса невозможны. Если попытаться использовать вне класса, например, такой оператор:

Console.Write ("count = {0 }", c1.count);

то компилятор сообщит об ошибке:

Error

1 ' Counter.count' is inaccessible due to its protection level

11.5. Ссылка this

Нестатические методы класса отличаются от статических наличием в первых

ссылки this "ссылки this" . Эта ссылка позволяет нестатическому методу "узнать",

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

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

объектом, для которого метод вызывается. Иногда ссылку this называют

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

Для избежания конфликта имён между параметрами метода и членами объекта.

Для организации связей между объектами одного класса.

Для обращения из одного конструктора класса к другому конструктору того же класса.

Для определения расширяющего метода (см [12] – стр. 1360; [1]).

Продемонстрируем первые две названные возможности применения ссылки this на следующем примере.

Определим класс Link, объекты которого можно объединять в цепочку в

односвязный список. Начало списка, то есть ссылку на первый объект, включённый в список, представим статическим полем класса ( static Link beg). Когда список пуст

значением beg будет null.

Программа с указанным классом:

// 11_05.cs - this и связный список using System;

class Link

{

static Link beg; Link next;

int numb;

public void add(int numb)

{

this.numb = numb;

if (beg == null) // список пуст { beg = this; return; }

Link temp = beg;

while (temp.next != null) temp = temp.next;

temp.next = this;

}

static public void display()

{

Link temp = beg; while (temp != null)

{

Console.Write(temp.numb + " "); temp = temp.next;

}

Console.WriteLine();

}

}

class Program

{

static void Main()

{

Link a = new Link(), b = new Link(), c = new Link(); a.add(7);

b.add(-4); c.add(0); Link.display();

}

}

Результат выполнения программы:

7 -4 0

Нестатическими полями класса являются int numb и Link next. Первое поле нужно нам только для иллюстрации, значением второго поля будет ссылка на следующий объект, подключённый к списку вслед за рассматриваемым.

Последовательность формирования списка из объектов класса Link можно показать

на рисунке.

Пустой список: beg=null

7

numb next

null

1

элемент:

beg

 

7

 

numb next

numb next

 

null

 

-4

элемента:

 

2

beg

 

Рис.11.1. Формирование списка объектов

Для создания объектов класса Link в программе использован конструктор без параметров, который автоматически встраивается в класс, когда в нём нет явно определённых конструкторов.

Для "подключения" объекта к списку введён нестатический открытый метод: public void add(int numb)

{

this.numb = numb;

if (beg == null) // список пуст { beg = this; return; }

Link temp = beg;

while (temp.next != null) temp = temp.next;

temp.next = this;

}

Особенность метода имя его параметра совпадает с именем поля класса.

Полное (квалифицированное) имя this.numb относится только к полю объекта.

Первое действие метода присваивание полю this.numb значения параметра с тем же именем. Применение ссылки this позволяет отличать поле объекта, для которого вызван метод add(), от одноимённого параметра.

По умолчанию статическое поле Link beg и нестатическое поле Link next

инициализируются значениями null. Пока список пуст поле beg сохраняет это пустое значение. Полю beg присваивается ссылка на первый объект класса Link, для которого будет вызван метод add(). Если в списке уже есть элементы (объекты класса Link), то создаётся локальная переменная Link temp, инициализированная значением ссылки beg. Далее в цикле перебираются все элементы списка пока не

будет найден элемент, которому никакой объект не подключён. Его полю, доступ к которому обеспечивает квалифицированное имя temp.next, присваивается значение ссылки this, т.е. ссылка на очередной объект класса Link, для которого вызван метод add().

Для последовательного перебора элементов списка и вывода значений полей

numb определён статический метод: static public void display()

{

Link temp = beg; while (temp != null)

{

Console.Write(temp.numb+" "); temp = temp.next;

}

Console.WriteLine();

}

В теле метода цикл, в котором локальная переменная temp (ссылка на объекты класса Link) последовательно адресует объекты списка, начиная с того, который ассоциирован со статической переменной beg.

Для иллюстрации возможностей класса Link в классе Program определён

метод Main():

static void Main()

{

Link a = new Link(), b = new Link(), c = new Link(); a.add(7);

b.add(-4); c.add(0);

Link.display();

}

Если в классе определены несколько нестатических конструкторов, то

зачастую удобно из одного конструктора обращаться к другому. Эту возможность,

как отмечено ранее, обеспечивает применение ссылки

this. Перед тем, как

рассмотреть эту роль служебного слова

this, рассмотрим нестатические

конструкторы.

 

 

11.6. Конструкторы объектов класса

Недостаток рассмотренных выше класса counter и класса Link –

невозможность определять объекты, начальные значения полей которых задаются вне объявления класса. Конструктор умолчания умеет создавать только объекты со значениями полей, определенными инициализацией. При создании любого объекта класса Real поле m равно 8.0 и поле p равно 0. Нужные программисту начальные

значения полей создаваемого объекта можно определять с помощью явно

 

объявленного в классе конструктора.

 

Конструктор объектов

"конструктор:конструктор объектов"

(иначе

экземпляров) класса это метод класса, в котором реализованы все действия,

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

Внешне любой конструктор это метод класса, имя которого всегда совпадает

с именем самого класса. Формат объявления конструктора:

модификаторы_конструктораopt

имя_конструктора (спецификация_параметровopt)

инициализатор_конструктораopt

тело_конструктора

Имя конструктора " конструктор:имя конструктора" имя именно того класса, которому конструктор принадлежит, других имен у конструктора не может быть.

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

В качестве модификаторов конструктора используются:

public, protected, internal, private, extern

Первые четыре модификатора это модификаторы доступа. Их назначение

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

Спецификация параметров конструктора может отсутствовать, но если она

есть, то содержит спецификации всех параметров конструктора.

 

 

Тело конструктора " конструктор:тело конструктора"

это: либо

блок

последовательность операторов, заключенная в фигурные скобки; либо

пустой

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

оператор в качестве тела используется только для конструкторов с модификатором extern. Мы будем в качестве тела конструктора использовать блок.

Назначение операторов тела конструктора

выполнить инициализацию

создаваемого объекта класса.

 

Инициализатор_конструктора

 

"конструктор:инициализатор_конструктора"

это специальное средство,

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

: base (список_аргументовopt)

Здесь base служебное слово "служебное слово: base" ; необязательный список аргументов список выражений, соответствующих параметрам вызываемого конструктора базового класса.

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

: this (список_аргументовopt)

Здесь this служебное слово "служебное слово: this" ; необязательный список аргументов список выражений, соответствующих параметрам другого

конструктора.

Соседние файлы в папке CSBasicCourse2ndedPodbelsky