logo search
C#, 320 стр

Класс Rational или структура Rational

Вернемся к классу Rational, спроектированному в предыдущей лекции. Очевидно, что его вполне разумно представить в виде структуры. Наследование ему не нужно. Семантика присваивания развернутого типа больше подходит для рациональных чисел, чем ссылочная семантика, ведь рациональные числа - это еще один подкласс арифметического класса. В общем, класс Rational - прямой кандидат в структуры. Зададимся вопросом, насколько просто объявление класса превратить в объявление структуры? Достаточно ли заменить слово class словом struct? В данном случае одним словом не обойтись. Есть одно мешающее ограничение на структуры. В конструкторе класса Rational вызывается метод nod, а вызов методов в конструкторе запрещен. Нетрудно обойти это ограничение, изменив конструктор, то есть явно задав вычисление общего делителя в его теле. Приведу текст этого конструктора:

public struct Rational

{

public Rational(int a, int b)

{

if(b==0) {m=0; n=1;}

else

{

//приведение знака

if( b<0) {b=-b; a=-a;}

//приведение к несократимой дроби

int p = 1, m1=a, n1 =b;

m1=Math.Abs(m1); n1 =Math.Abs(n1);

if(n1>m1){p=m1; m1=n1; n1=p;}

do

{

p = m1%n1; m1=n1; n1=p;

}while (n1!=0);

p=m1;

m=a/p; n=b/p;

}

}//Конструктор

//поля и методы класса

}

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

public void TwoSemantics()

{

Rational r1 = new Rational(1,3), r2 = new Rational(3,5);

Rational r3, r4;

r3 = r1+r2; r4 = r3;

if(r3 >1) r3 = r1+r3 + Rational.One;

else r3 = r2+r3 - Rational.One;

r3.PrintRational("r3"); r4.PrintRational("r4");

}

В этом примере используются константы, работает статический конструктор, закрытый конструктор, перегруженные операции сравнения, арифметические выражения над рациональными числами. В результате вычислений r3 получит значение 8/15, r4- 14/15. Заметьте, аналогичный пример для класса Rational даст те же результаты. Для класса Rational и структуры Rational нельзя обнаружить разницу между ссылочным и развернутым присваиванием. Это связано с особенностью класса Rational - он по построению относится к неизменяемым (immutable) классам, аналогично классу String. Операции этого класса не изменяют поля объекта, а каждый раз создают новый объект. В этом случае можно считать, что объекты класса обладают присваиванием развернутого типа.