Файл: 10. Разработка универсальных полиморфных контейнеров.pdf

Добавлен: 20.10.2018

Просмотров: 964

Скачиваний: 9

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

 

 

   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  мало 

отличается  от  старой  и  приводится  здесь  для  того,  чтобы  еще  раз  обратить 


background image

 

 

внимание  на  технику  использования  методов  доступа  для  вызова  методов 

отображения графических объектов. 

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)  {   // код перемещения  } 


background image

 

 

   public   void   MoveOnly (int  dx, int  dy, string   aName ) { // код выборочного } 

   public   string  GetObjectName (int  ai){ // код получения имени объекта } 

 };   //  конец описания класса

 

 

В  заключение  отметим,  что  во  всех  стандартных  библиотеках  классов, 

поддерживающих  объектные  языки,  реализованы  различные  стандартные 

контейнеры/коллекции.  Реализация  этих  контейнеров  использует  понятие 

интерфейса,  которое  изучается  в  следующем  разделе  пособия,  поэтому 

краткая  характеристика  стандартных  контейнеров  будет  рассмотрена 

несколько позже. 

Второй пример не связан с графическими объектами, но в то же время 

использует все рассмотренные ранее механизмы. 

Постановка задачи. В организации работают сотрудники двух типов с 

разными формами оплаты: 

 

на основе фиксированного оклада и доли ставки: зарплата = оклад * 

ставка  

 

на основе почасовой оплаты: зарплата = число_отработанных_часов * 

стоимость_часа 

Требуется  создать  универсальную  объектную  программу  для  организации 

хранения данных о сотрудниках и начисления им зарплаты. 

Как обычно, разработку проведем по шагам. 

Шаг 1. Анализ задачи с выделением возможных объектов. 

Можно предложить следующие объекты: 

-  сотрудник-окладник: фамилия, должность, оклад, ставка, расчет зарплаты 

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

ставка, расчет зарплаты 

-  объект-контейнер «Коллектив»: число сотрудников, полиморфное 

хранилище ссылок на сотрудников разных типов, добавление и удаление 

сотрудников, формирование зарплатной ведомости 


background image

 

 

Шаг 2. Анализ объектов.  

Объекты  первых  двух  типов  имеют  общие  данные  и  общее  поведение  и 

могут  рассматриваться  как  разновидности  общего  понятия  «Сотрудник», 

следовательно,  можно  построить  небольшую  иерархию  классов.  Корневой 

класс  должен  содержать  общие  данные,  такие  как  фамилия  и  должность,  а 

также  определять  общую  функциональность,  такую  как  начисление 

зарплаты. 

Шаг 3. Проектирование необходимых классов 

Введем следующие классы: 

 

- абстрактный корневой класс Сотрудник: фамилия, должность, 

конструктор, методы доступа, абстрактный метод расчета зарплаты 

 

- производный класс Окладник: оклад, ставка, конструктор, методы 

доступа, переопределенный метод расчета зарплаты 

 

- производный класс Почасовик: часовая ставка, количество отработанных 

часов, конструктор, методы доступа, переопределенный метод расчета 

зарплаты 

 

- класс контейнерных объектов на основе массива полиморфных ссылок на 

сотрудников разных типов 

Шаг 4. Формальное описание классов создаваемой иерархии.  

Код на языке Delphi/Free Pascal

 

 

TSotr  = class 

 

 

// базовый абстрактный класс 

   private   fam, dolgn : string ;

 

 

// общие свойства 

   public   constructor  Create (aFam, aDolgn : string ); 

      // открытые методы доступа к общим свойствам 

                function   Zarplata : realvirtualabstract;  // абстрактный метод 

end;

 


background image

 

 

 

TSotrOklad = class (TSotr)

   

// первый дочерний класс 

    private   oklad : integer;

   

// новые уникальные свойства 

                   stavka : real

    public  constructor  Create (aFam, aDolgn : string; aOklad : integer; aStavka 

real);                

            // методы доступа к новым свойствам 

                 function   Zarplata : realoverride;

 

// переопределение метода 

end;

 

 

TSotrPochas = class (TSotr)

  

// второй дочерний класс 

   private   OtrabChas, ChasStavka : integer;

 

// свои уникальные свойства 

   public  constructor  Create ( aFam, aDolgn : string; aOtrChas, aChasSt : 

integer ); 

               // методы доступа к новым свойствам 

               function   Zarplata : realoverride;

 

// переопределение метода 

end;

 

 

// реализация всех методов вполне очевидна

 

 

Код на языке C# 

abstract   class   Сотрудник 

{   private   string   Фам, Должн; 

    public   Сотрудник (string   фам,   string   должн) { …} 

    // открытые методы доступа 

    public   abstract    virtual   float   Расчет( );