logo
C#, 320 стр

Константы класса Rational

Рассмотрим важную проблему определения констант в собственном классе. Определим две константы 0 и 1 класса Rational. Кажется, что сделать это невозможно из-за ограничений, накладываемых на объявление констант. Напомню, константы должны быть инициализированы в момент объявления, и их значения должны быть заданы константными выражениями, известными в момент компиляции. Но в момент компиляции у класса Rational нет никаких известных константных выражений. Как же быть? Справиться с проблемой поможет статический конструктор, созданный для решения подобных задач. Роль констант класса будут играть статические поля, объявленные с атрибутом readonly, то есть доступные только для чтения. Нам также будет полезен закрытый конструктор класса. Еще укажем, что введение констант класса требует использования экзотических средств языка C#. Вначале определим закрытый конструктор:

private Rational(int a, int b, string t)

{

m = a; n = b;

}

Не забудем, что при перегрузке методов (в данном случае конструкторов) сигнатуры должны различаться, и поэтому пришлось ввести дополнительный аргумент t для избежания конфликтов. Поскольку конструктор закрытый, то гарантируется корректное задание аргументов при его вызове. Определим теперь константы класса, которые, как я уже говорил, задаются статическими полями с атрибутом readonly:

//Константы класса 0 и 1 - Zero и One

public static readonly Rational Zero, One;

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

static Rational()

{

Console.WriteLine("static constructor Rational");

Zero = new Rational(0, 1, "private");

One = new Rational (1, 1, "private");

}//Статический конструктор

Как это все работает? Статический конструктор вызывается автоматически один раз до начала работы с объектами класса. Он и задаст значения статических полей Zero, One, представляющих рациональные числа с заданным значением. Поскольку эти поля имеют атрибут static и readonly, то они доступны для всех объектов класса и не изменяются в ходе вычислений, являясь настоящими константами класса. Прежде чем привести пример работы с константами, давайте добавим в наш класс важные булевы операции над рациональными числами - равенство и неравенство, больше и меньше. При этом две последние операции сделаем перегруженными, позволяя сравнивать рациональные числа с числами типа double:

public static bool operator ==(Rational r1, Rational r2)

{

return((r1.m ==r2.m)&& (r1.n ==r2.n));

}

public static bool operator !=(Rational r1, Rational r2)

{

return((r1.m !=r2.m)|| (r1.n !=r2.n));

}

public static bool operator <(Rational r1, Rational r2)

{

return(r1.m * r2.n < r2.m* r1.n);

}

public static bool operator >(Rational r1, Rational r2)

{

return(r1.m * r2.n > r2.m* r1.n);

}

public static bool operator <(Rational r1, double r2)

{

return((double)r1.m / (double)r1.n < r2);

}

public static bool operator >(Rational r1, double r2)

{

return((double)r1.m / (double)r1.n > r2);

}

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

public void TestRationalConst()

{

Rational r1 = new Rational(2,8), r2 =new Rational(2,5);

Rational r3 = new Rational(4, 10), r4 = new Rational(3,7);

Rational r5 = Rational.Zero, r6 = Rational.Zero;

if ((r1 != Rational.Zero) && (r2 == r3))r5 =

(r3+Rational.One)*r4;

r6 = Rational.One + Rational.One;

r1.PrintRational("r1: (2,8)");

r2.PrintRational ("r2: (2,5)");

r3.PrintRational("r3: (4,10)");

r4.PrintRational("r4: (3,7)");

r5.PrintRational("r5: ((r3 +1)*r4)");

r6.PrintRational("r6: (1+1)");

}

Результаты работы этого примера показаны на рис. 16.6.

Рис. 16.6.  Константы и выражения типа Rational