Лого на 91. НЕГ „Проф. Константин Гълъбов“

Модул 1 · Урок 20

Обектно-ориентиран подход

Обобщение на темата чрез довършване на класа Rational: съкращаване на дроби с НОД, нормализирано извеждане и извеждане в десетичен вид.

Какво минахме дотук

Това е обобщителният урок на темата „Обектно-ориентиран подход“. Няма нови понятия — има един клас, който ще довършим както трябва.

ПонятиеКакво еОт кой урок
ОбектКомпютърен модел на реален или абстрактен обект14
КласТип, обединяващ атрибути и методи на еднотипни обекти14, 15
АтрибутХарактеристика, съхранена в паметта на обекта15, 16
МетодФункция, която извършва обработка над обекта17
КонструкторМетод с името на класа, който създава инстанцията18
РеференцияСтойността на променлива от клас — адрес, не обект19

Ключово

Класът Rational го влачим от урок 8. Тогава беше две цели числа и купчина формули. Сега ще стане нещо, което наистина може да се ползва.

Задача 1 — съкратени дроби

При изпълнението на достатъчно примери на програмата Rational ще забележиш, че пресметнатите резултати са необичайни. Получените дроби често имат числител и знаменател, които се делят на някакво число. Такава форма на правилната дроб се нарича несъкратена.

Обикновено е дробите да се показват в съкратен вид. За целта числителят и знаменателят трябва да се разделят на най-големия им общ делител — НОД(num, denum). Алгоритъмът на Евклид вече го знаеш от урок 12; сега го оформяме като метод на класа:

private int GCD(int a, int b)
{
    int tmp, r;
    if (a < b) { tmp = a; a = b; b = tmp; }
    while (b != 0)
    {
        r = a % b; a = b; b = r;
    }
    return a;
}

Бележка

Забележи private вместо public. Този метод е вътрешна кухня на класа — потребителят му няма работа с него. Точно за това служи капсулацията от урок 16.

Сега методът за събиране добива вида:

public void Add(Rational r)
{
    this.num = this.num * r.denum + r.num * this.denum;
    this.denum = this.denum * r.denum;
    int g = GCD(num, denum);
    this.num = this.num / g;
    this.denum = this.denum / g;
}

Модифицирай по същия начин и останалите методи за извършване на аритметичните операции.

Задача 2 — нормализирано извеждане

Едно друго необичайно нещо при извеждане на дробните числа е извеждането на целите числа като дроби със знаменател 1, както и извеждането на дробите, чиято стойност е 0, със знаменател. Добави в класа метод, който нормализира тези случаи:

public void normPrint()
{
    if (this.denum == 1) Console.WriteLine(this.num);
    else if (this.num == 0) Console.WriteLine("0");
    else Console.WriteLine(this.num + "/" + this.denum);
}
ДробPrint()normPrint()
5/15/15
0/70/70
3/43/43/4

Контрол и оценка

Задача 1 — извеждане в десетичен вид

При създаването на класа Rational предвидихме атрибут, който да съхранява правилната дроб и като десетична. Добави в класа метод public void decPrint(), който извежда инстанция на класа във вид на десетична дроб, с аргумент броя на цифрите след десетичната точка.

Съвет

Указание: използвай метода Math.Round(), за да „изрежеш“ ненужните цифри. Внимавай с целочисленото деление — num / denum при два int дава цяло число.

Още за проверка

1. Модифицирай всички аритметични методи да съкращават резултата. Компилирай и провери с различни примери.

2. Модифицирай програмата Rational така, че да използва метода за извеждане на дробите в нормализиран вид.

3. Какво се случва, ако някой създаде дроб със знаменател 0? Как би защитил класа от това?

Какво трябва да запомниш

  • Вътрешните помощни методи се правят private — потребителят на класа не бива да ги вижда.
  • Съкращаването на дроб е деление на числителя и знаменателя на НОД(num, denum).
  • Един добър клас не само смята вярно, а и показва резултата в очаквания вид — оттам са normPrint и decPrint.
  • При int / int в C# резултатът е цяло число. За десетичен вид поне единият операнд трябва да е дробен.
  • Формулите не изчезват в ООП — те се преместват там, където им е мястото: вътре в класа.