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

Класс как совокупность статических членов

10.1. Статические члены класса

Мы уже отмечали, что класс в общем случае представляет собой «трафарет» для создания объектов (этого класса) и «оболочку», в которую заключены статические члены (например, поля и методы). Остановимся подробнее на второй из названных ролей класса – рассмотрим класс как совокупность статических членов. При этом обратим внимание читателя, что в программе кроме класса, включающего метод Main(), может присутствовать любое число других классов. В этой главе будем определять классы с помощью объявлений такого формата:

class имя_класса тело_класса

Здесь class служебное (ключевое) слово; имя_класса – идентификатор, выбранный программистом в качестве имени класса; тело_класса – заключенная в фигурные скобки последовательность объявлений (деклараций) статических членов класса. (Сразу же отметим, что статический характер членов класса – это совсем необязательная их особенность, а ограничение, которого мы будем придерживаться в этой главе.)

Имеется две разные возможности определить член класса как статический. С помощью модификатора static объявляются статические:

поле (field); метод (method);

свойство (property); событие (event); операция (operator); конструктор (constractor).

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

константы; локализованные в классе типы (например, вложенные классы).

Класс как совокупность статических членов

175

 

 

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

При объявлении члена класса он может быть снабжен одним или несколькими модификаторами. В этой главе нам полезно познакомиться со следующими модификаторами: static, public, protected, internal, private, readonly, volatile. Модификатор static

мы уже назвали. Применялся в предыдущих программах и модификатор public. Его назначение – сделать член класса доступным из-вне объявления класса. Имеются и другие возможности влиять на доступность членов класса. Проще всего объяснить правила доступа к членам классов, рассмотрев вначале список модификаторов доступа:

public

доступен без ограничений всем методам всех

(открытый)

сборок;

protected

доступен в классе и в любом классе,

(защищещенный)

производном от данного;

internal

доступен везде в пределах сборки;

(внутренний)

 

protected internal

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

(защищенный

и в любом классе, производном от данного;

внутренний)

 

private

доступен только в классе и вложенных в него

(закрытый)

типах (классах).

В объяснении модификаторов доступа нам впервые встречается термин «сборка» (assembly). В Стандарте C# [2] сборка определяется как совокупность из одного или нескольких файлов, которые создает компилятор как результат компиляции программы. В зависимости от того, какие средства и режимы компиляции выбраны, можно создать однофайловую или многофайловую сборку. Сборка позволяет рассматривать группу файлов как единую сущность. Сейчас достаточно, чтобы читатель знал о существовании такого понятия.

Каждый член класса может быть снабжен одним и только одним модификатором доступа. По умолчанию (при отсутствии модификатора) члену приписывается статус доступа private, т. е.

176

Г л а в а 1 0

 

 

член класса недоступен вне класса, где он объявлен.

Для обращения к статическому члену класса используется квалифицированное имя:

имя_класса.имя_члена

Так как мы уже использовали статические члены библиотечных классов, например, Math.PI и Console.WriteLine(), то нам уже знаком этот синтаксис.

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

Внимание! Никакие операторы, отличные от объявлений, в классе недопустимы!

10.2. Поля классов (статические поля)

Как формулирует стандарт языка C#, поле — это член класса, который представляет переменную, ассоциированную с объектом или классом. Поле – это объявление данных (константы, переменной, объекта), принадлежащих либо классу в целом, либо каждому из его объектов. Чтобы поле принадлежало не объекту, а классу и могло использоваться до определения объектов этого класса, его объявляют статическим, используя модификатор static. Если в объявлении поля этот модификатор отсутствует, то поле является полем объектов. В этом случае полю выделяется память, и оно становится доступным для использования только при и после создания объекта. Статическое поле размещается в памяти в момент загрузки кода класса. Статическое поле (поле класса) доступно для использования и до, и после создания объектов класса.

Объявление статистического поля имеет вид:

модификаторы opt static

тип_поля список_объявлений;

Индекс opt указывает на необязательность модификаторов, отличных от static. В качестве этих необязательных модификаторов поля могут использоваться уже перечисленные модификаторы доступа public, private, protected, internal. Кроме них в объявление поля могут входить модификаторы:

Класс как совокупность статических членов

177

 

 

new – применяется при наследовании (см. главу 13); readonly – запрещает изменять значение поля. Поле получает

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

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

Зачастую список объявлений поля содержит только одно объявление. Каждое объявление в списке имеет следующий вид:

идентификатор инициализатор_поля opt

Индекс opt указывает на необязательность инициализатора поля. Если в объявлении поля отсутствует инициализатор, то инициализация выполняется по умолчанию значением соответствующего типа. В соответствии с общей концепцией типов языка C# поля могут иметь типы ссылок и типы значений. Возможны

следующие формы инициализаторов полей:

=выражение

=инициализатор_массива

=new тип (аргументы_конструктора)

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

Нестатические члены невозможно использовать в инициализирующем выражении статического поля.

Пример инициализации и использования статических полей:

// 10_01.cs статические поля класса using System;

class T {

int x; // Поле объектов класса

static int y = 3; // y = x + 5; - ошибка: х – поле объекта public static int z = 5 - y; // Эквивалент: z = 5 - T.y;

178

Г л а в а 1 0

 

 

}

class Program

{

static void Main()

{

// Console.WriteLine("T.y = " + T.y); // Error! T.y is private! int z = T.z; // z и T.z - разные переменные! Console.WriteLine("T.z = " + ++T.z); // Изменяется T.z Console.WriteLine("z = {0}", z);

}

}

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

T.z = 3 z = 2

Следует отметить одну особенность инициализации статических полей. Вначале они все получают умалчиваемые значения (для арифметических типов – нулевые). Затем последовательно (сверху вниз) выполняются инициализаторы. Тем самым, если в инициализирующее выражение входит в качестве операнда статическое поле, которое еще не инициализировано явно, то для него берется умалчиваемое (например, нулевое) значение. В качестве примера рассмотрим программу:

// 10_02.cs статические поля класса порядок

инициализации using System; class T

{

public static int x = y; static int y = 3;

public static int z = y;

}

class Program

{

static void Main()

{

Console.WriteLine("T.x = " + T.x);

Console.WriteLine("T.z = " + T.z);

Класс как совокупность статических членов

179

 

 

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

T.x = 0

T.z = 3

Обратите внимание, что поле y по умолчанию закрытое (имеет статус доступа private), и обращение к нему невозможно вне класса T.

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

// 10_03.cs статические поля разных классов using System;

class c1

{

public static double orbit = 2 * c2.pi * c3.radius;

}

class c2

{

public static double pi = double.Parse(c3.str);

}

class c3

{

public static string str = "3,14159"; public static double radius = 10;

}

class Program

{

static void Main()

{

Console.WriteLine("c1.orbit = {0}", c1.orbit); c3.radius = 20;

Console.WriteLine("c3.radius = {0}", c3.radius); Console.WriteLine("c1.orbit = {0}", c1.orbit);

}

}

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

}

c1.orbit = 62,8318

}

c3.radius = 20

 

c1.orbit = 62,8318

180

Г л а в а 1 0

 

 

Инициализация статических полей выполняется только однажды. Поэтому значение поля c1.orbit не изменилось после изменения c3.radius в методе Main().

10.3. Статические константы

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

Объявление статической константы имеет вид:

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

список_объявлений_констант

Необязательные модификаторы для констант – это при отсутствии наследования модификаторы доступа (public, private, protected, internal).

Объявление из списка_объявлений_констант имеет вид:

идентификатор=инициализирующее_выражение.

Идентификатор служит именем статической константы. В инициализирующее выражение имеют право входить только константы–литералы и статические константы. (Порядок их размещения в объявлении класса безразличен.) Каждая константа должна быть обязательно явно инициализирована. Умалчиваемые значения для статических констант не предусмотрены.

Пример с классом статических констант:

// 10_04.cs статические константы класса using System;

class Constants

{

public const double скорость_света = 299793; // км/сек public const double радиус_электрона = 2.82e-13; // см

}

class Program

{

static void Main()

{

Console.WriteLine("радиус_электрона = {0}",

Класс как совокупность статических членов

181

 

 

Constants.радиус_электрона);

}

}

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

радиус_электрона = 2,82E-13

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

// 10_05.cs статические константы разных классов using System;

class One

{

public const double circle = 2 * pi * Two.radius; public const double pi = 3.14159;

}

class Two

{

public const double radius = 20;

}

class Program

{

static void Main()

{

Console.WriteLine("One.circle = {0}", One.circle);

}

}

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

One.circle = 125,6636

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

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