Скачиваний:
62
Добавлен:
24.03.2015
Размер:
165.38 Кб
Скачать

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

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

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

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

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

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

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

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

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

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

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

class Lekc10_04

{

class Constants

{

public const double скорость_света = 299793; // км/сек

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

}

public static void Main()

{

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

}

}

Результат выполнения программы: радиус_электрона = 2,82Е-13

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

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

class Lekc10_05

{

class One

{

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

public const double pi = 3.14159;

}

class Two

{

public const double radius = 20;

}

public static void Main()

{

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

}

}

Результат выполнения программы: One.circle = 125,6636

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

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

public const double pi=3.14159;

В инициализатор константы circle входит константа pi, объявление которой следует за объявлением circle. Несмотря на это значением circle будет 125,6636. Конечно, при инициализации нескольких констант недопустимо появление "зацикливания". В инициализатор константы К1 не должна входить константа К2, в инициализатор которой входит константа К1.

Указанное "зацикливание" никогда не возникает при инициализации статических полей (даже имеющих модификатор readonly). Поле F2, объявление которого размещено ниже, может входить в инициализатор поля F1 - оно имеет там умалчиваемое значение. При этом поле F1, использованное в инициализатор F2, будет иметь там уже конкретное значение. Замена const на static readonly в предыдущем примере:

public static readonly double circle = 2*pi*Two.radius;

public static readonly double pi=3.14159;

При такой инициализации значение circle будет 0.

10.4. Статические методы

Статический метод Main() мы уже используем, начиная с первой программы этой книги. Нам уже известно, что в теле метода Main() можно обращаться ко всем статическим членам того класса, где размещён метод Main().

Статические методы, отличные от Main(), мы уже подробно рассматривали, но ограничивались их размещением в том классе, где находится метод Main(). В этом случае для обращения к методу можно использовать выражение имя_метода(список_аргументов). Если статический метод определён в другом классе, то для обращения к нему используется выражение вида:

имя_класса.имя_метода(список_аргументов)

По умолчанию статический метод имеет модификатор доступа private, т.е метод доступен только внутри класса. В объявлении статического метода, который планируется вызывать вне класса, необходимо указать модификатор доступа. В зависимости от дальнейшего применения метода используются модификаторы public (открытый), protected - (защищещённый), internal -(внутренний), protected internal - (защищенный внутренний). Области видимости, которые обеспечены перечисленными модификаторами, те же что и для полей классов.

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

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

// 10_06.cs - статические методы класса

class Lekc10_06

{

class newClass

{

static int n = 5;

static int x = fl(n);

public static int у = fb(n) ? 10 : -10;

public static int getX() { return x; }

static bool fb(int a) { return a % 2 == 0 ? true : false; }

static int fl(int d) { return d * d * d; }

}

public static void Main()

{

Console.WriteLine("newClass.у = " + newClass.у);

Console.WriteLine("newClass.getX() = " + newClass.getX());

}

}

Результат выполнения программы: newClass.у = -10

newClass.getX() = 125

Обратие внимание, что в классе newClass только два открытых члена -поле int у и метод getX(). Поля х, n и методы fb(), fl() недоступны вне класса.

В теле любого метода могут быть объявлены локальные переменные и константы с типами ссылок и значений. Имена таких переменных имеют право совпадать с именами статических членов того класса, в котором размещён метод. В этом случае локальная переменная "экранирует" одноимённую статическую переменную. То есть имя без квалификатора "имя_класса." при совпадении имён относится только к локальному объекту метода. В качестве примера рассмотрим следующий метод Main() из класса Test_cs:

// 10_07.cs - Статические поля класса и локальные данные методов

class Lekc10_07

{

public class Test_cs

{

public static int n = 10; // инициализация разрешена

public static string line = new string('*', n);

public static double constant = 9.81; // поле класса Test_cs

double pi = 3.14159; // поле объекта класса Test_cs

public static void Main()

{

const double PI = 3.14159; // локальная константа

double circle; // локальная переменная

//circle = 2 * pi * n; // ошибка - нет объекта класса Test_cs

circle = 2 * PI * n;

Console.WriteLine("Длина окружности=" + circle.ToString());

Console.WriteLine(Test_cs.line);

Test_cs.n = 20; // изменили значение поля класса

Test_cs.line = new string('*', n); // изменили значение ссылки

Console.WriteLine(Test_cs.line);

const double constant = 2.718282; // локальная константа

Console.WriteLine("Test_cs.constant=" + Test_cs.constant);

Console.WriteLine("constant=" + constant);

}

}

}

Результат выполнения программы: Длина окружности=62,8318

**********

********************

Test_cs.constant=9,81 constant=2,718282

В тексте метода Main(): PI - локальная именованная константа; circle - локальная переменная;

n, Test_cs.n - два обращения к одному и тому же статическому полю класса; line - статическая ссылка-поле класса;

constant - локальная константа, имя которой совпадает с именем статического поля класса Test_cs.

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

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

Итак, пока не создан объект класса, существуют и доступны только статические члены класса.

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