Загрузка...

Лабораторная работа. Построение списка с суммирующим полем.


Лабораторная работа по предмету Объектно-ориентированное программирование. Построение списка с суммирующим полем.

Нам необходимо иметь специализированный вариант нашего списка (OneLinkList),
элементы которого допускали бы операцию сложения и одно из полей которого сохраняло бы
сумму всех элементов, добавленных в список.


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

Начнем с определения класса Calc:
public abstract class Calc{
public abstract T Add(T a, T b);
public abstract T Sub(T a, T b);
public abstract T Mult(T a, T b);
public abstract T Div(T a, T b);
}
Наш абстрактный универсальный класс определяет четыре арифметические операции.
Давайте построим трех его конкретизированных потомков:
public class IntCalc : Calc{
public override int Add(int a, int b) { return (a + b);}
public override int Sub(int a, int b) { return (a — b);}
public override int Mult(int a, int b) { return (a * b);}
public override int Div(int a, int b) { return (a / b); }
}
public class DoubleCalc : Calc{
public override double Add(double a, double b) {return (a + b);}
public override double Sub(double a, double b) {return (a — b);}
public override double Mult(double a, double b) {return (a * b);}
public override double Div(double a, double b) {return (a / b);}
}
public class StringCalc : Calc{
public override string Add(string a, string b) {return (a + b);}
public override string Sub(string a, string b) {return (a );}
public override string Mult(string a, string b) {return (a );}
public override string Div(string a, string b) {return (a);}
}
Здесь определяются три разных калькулятора: один — над целочисленными данными,
другой — над данными с плавающей точкой, третий — над строковыми данными. В последнем
случае определена, по сути, только операция сложения строк (конкатенации).
Теперь нам нужно ввести изменения в ранее созданный класс OneLinkList. Обратите
внимание на важный технологический принцип работы с объектными системами. Пусть уже
есть нормально работающий класс с нормально работающими клиентами класса. Не следует
изменять этот класс. Класс закрыт для изменений. Используйте наследование и открывайте
класс-потомок, в который и вносите изменения, учитывающие добавляемую специфику класса.
Принцип «Закрыт — Открыт» является одним из важнейших принципов построения
программных систем в объектном стиле.
В полном соответствии с этим принципом построим класс SumList — потомок класса
OneLinkList. То, что родительский класс является универсальным, ничуть не мешает строить
потомка класса, сохраняющего универсальный характер родителя.
public class SumList<K, T> : OneLinkList<K, T> where K :
IComparable{
Calc calc;
T sum;
public SumList(Calc calc) { this.calc = calc; sum = default(T); }
public new void add(K key, T item)
{
Node<K, T> newnode = new Node<K, T>();
if (first == null) { first = newnode; cursor = newnode; }
else { newnode.next = cursor.next; cursor.next = newnode; }
newnode.key = key; newnode.item = item;
sum = calc.Add(sum, item);
}
public T Sum() {return (sum); }
}//SumList
У класса добавилось поле sum, задающее сумму хранимых элементов, и поле calc —
калькулятор, выполняющий вычисления. Метод add, объявленный в классе с модификатором
new, скрывает родительский метод add, задавая собственную реализацию этого метода. К
классу добавился еще один запрос, возвращающий значение поля sum.
Проведем теперь эксперименты с новыми вариантами списков, допускающих
суммирование элементов:
public void TestSum()
{
SumList<string, int> list1 = new SumList<string, int>(new IntCalc());
list1.add(«Петр», 33); list1.add(«Павел», 44);
Console.WriteLine(«sum= {0}», list1.Sum()); //77
SumList<string, double> list2 = new SumList<string, double> (new DoubleCalc());
list2.add(«Петр», 33.33); list2.add(«Павел», 44.44);
Console.WriteLine(«sum= {0}», list2.Sum()); //77.77
SumList<string, string> list3 = new SumList<string, string> (new StringCalc());
list3.add(«Мама», » Мама мыла «); list3.add(«Маша», «Машу мылом!»);
Console.WriteLine(«sum= {0}», list3.Sum()); // Мама мыла Машу мылом!
}
Обратите внимание на создание списков:
SumList<string, int> list1 = new SumList<string, int>(new IntCalc());
SumList<string, double> list2 = new SumList<string, double>(new DoubleCalc());
SumList<string, string> list3 = new SumList<string, string>(new StringCalc());
Как видите, конструктору объекта передается калькулятор, согласованный с типами
данных, которые хранятся в списке.

Загрузка...