Файл: 10. Разработка универсальных полиморфных контейнеров.pdf
ВУЗ: Университет управления «ТИСБИ»
Категория: Учебное пособие
Дисциплина: Объектно-ориентированное программирование
Добавлен: 20.10.2018
Просмотров: 1060
Скачиваний: 9
public void SetNext (ListItem aNext) {…;} // изменить адрес след. эл-та
public void SetFig (Figure aFig) {…}; // для присоедин. другого объекта
public void SetInf (int aInf); // для изменения информационного поля
};
Программная реализация методов вполне очевидна
Измененное и расширенное описание универсального спискового
контейнера для графических объектов:
FigsListContainer = class
private
ContInf : string;
First : ListItem; // указатель на первый элемент списка
public
сonstructor Create (ainf : string); // создание пустого списка
function GetFirst : ListItem;
// здесь должны быть методы доступа к информационному свойству
procedure Add (ainf : string; aFig : TFigure); // добавление объекта
function Delete (ainf : string) : boolean; // удаление эл-та по его инф. части
function Search (aName : sring) : ListItem; // поиск по имени объекта
procedure ShowAll; // отображение всех объектов
procedure ShowOnly (aName : string); // выборочное отображение
procedure MoveAll (dx, dy : integer); // перемещение всех объектов
procedure MoveOnly (dx, dy : integer; aName : string); // выборочное
function GetObjectName (ai : integer): string; // получение имени объекта
end;
В качестве примера программной реализации приведем только метод
ShowAll, поскольку реализация других методов практически совпадает с
рассмотренной ранее. Да и новая реализация метода ShowAll мало
отличается от старой и приводится здесь для того, чтобы еще раз обратить
внимание на технику использования методов доступа для вызова методов
отображения графических объектов.
procedure FigsListContainer.ShowAll;
var Temp : ListItem; // вспом. переменная для прохода по списку
begin
Temp := First;
while (Temp <> nil) do
begin
Temp.GetFig.Show; // доступ к методу текущего объекта
Temp := Temp.GetNext; // получение адреса след. элемента
end;
end;
class FigsListContainer {
private ListItem First; // указатель на первый элемент списка
private int ContInf;
public CircleListContainer (int ainf) { First = null ; ContInf = ainf;}
public void Add(Figure aFig, int ainf)
{ First = new ListItem (ainf, First, aFig) ;} // красиво и компактно!
public void ShowAll ( )
{ ListItem Temp = First; // вспом. указатель для прохода по списку
while (Temp != null )
{ Temp.GetFig( ).Show ( ); // доступ к методу текущего объекта
Temp = Temp.GetNext ( ); // доступ к адресному полю
} // конец цикла
} // конец метода отображения
public int SearchName (string aName) { // код поиска по имени }
public void ShowOnly(string aName) {//код выборочного отображения }
public void MoveAll (int dx, int dy) { // код перемещения }
public void MoveOnly (int dx, int dy, string aName ) { // код выборочного }
public string GetObjectName (int ai){ // код получения имени объекта }
}; // конец описания класса
В заключение отметим, что во всех стандартных библиотеках классов,
поддерживающих объектные языки, реализованы различные стандартные
контейнеры/коллекции. Реализация этих контейнеров использует понятие
интерфейса, которое изучается в следующем разделе пособия, поэтому
краткая характеристика стандартных контейнеров будет рассмотрена
несколько позже.
Второй пример не связан с графическими объектами, но в то же время
использует все рассмотренные ранее механизмы.
Постановка задачи. В организации работают сотрудники двух типов с
разными формами оплаты:
на основе фиксированного оклада и доли ставки: зарплата = оклад *
ставка
на основе почасовой оплаты: зарплата = число_отработанных_часов *
стоимость_часа
Требуется создать универсальную объектную программу для организации
хранения данных о сотрудниках и начисления им зарплаты.
Как обычно, разработку проведем по шагам.
Шаг 1. Анализ задачи с выделением возможных объектов.
Можно предложить следующие объекты:
- сотрудник-окладник: фамилия, должность, оклад, ставка, расчет зарплаты
- сотрудник-почасовик: фамилия, должность, отработанные часы, часовая
ставка, расчет зарплаты
- объект-контейнер «Коллектив»: число сотрудников, полиморфное
хранилище ссылок на сотрудников разных типов, добавление и удаление
сотрудников, формирование зарплатной ведомости
Шаг 2. Анализ объектов.
Объекты первых двух типов имеют общие данные и общее поведение и
могут рассматриваться как разновидности общего понятия «Сотрудник»,
следовательно, можно построить небольшую иерархию классов. Корневой
класс должен содержать общие данные, такие как фамилия и должность, а
также определять общую функциональность, такую как начисление
зарплаты.
Шаг 3. Проектирование необходимых классов
Введем следующие классы:
- абстрактный корневой класс Сотрудник: фамилия, должность,
конструктор, методы доступа, абстрактный метод расчета зарплаты
- производный класс Окладник: оклад, ставка, конструктор, методы
доступа, переопределенный метод расчета зарплаты
- производный класс Почасовик: часовая ставка, количество отработанных
часов, конструктор, методы доступа, переопределенный метод расчета
зарплаты
- класс контейнерных объектов на основе массива полиморфных ссылок на
сотрудников разных типов
Шаг 4. Формальное описание классов создаваемой иерархии.
Код на языке Delphi/Free Pascal
TSotr = class
// базовый абстрактный класс
private fam, dolgn : string ;
// общие свойства
public constructor Create (aFam, aDolgn : string );
// открытые методы доступа к общим свойствам
function Zarplata : real; virtual; abstract; // абстрактный метод
end;
TSotrOklad = class (TSotr)
// первый дочерний класс
private oklad : integer;
// новые уникальные свойства
stavka : real;
public constructor Create (aFam, aDolgn : string; aOklad : integer; aStavka
: real);
// методы доступа к новым свойствам
function Zarplata : real; override;
// переопределение метода
end;
TSotrPochas = class (TSotr)
// второй дочерний класс
private OtrabChas, ChasStavka : integer;
// свои уникальные свойства
public constructor Create ( aFam, aDolgn : string; aOtrChas, aChasSt :
integer );
// методы доступа к новым свойствам
function Zarplata : real; override;
// переопределение метода
end;
// реализация всех методов вполне очевидна
Код на языке C#
abstract class Сотрудник
{ private string Фам, Должн;
public Сотрудник (string фам, string должн) { …}
// открытые методы доступа
public abstract virtual float Расчет( );