TURBO PASCAL

Новости

Программы   

Turbo Pascal 

Игры

Документация   

Странности

FAQ

Ссылки

Форум

Живой Журнал

Гостевая книга

Рассылка

Благодарности

Об авторе

ООП - это очень просто

Выпуск № 3

- Как написать неработоспособного монстра ?
- Воспользоваться всеми этими советами одновременно!

В этом выпуске:
  1. Венгерская нотация;
  2. Способы защиты переменных
  3. Пример объекта, хранящего информацию в файле
  4. Оцените "стандартный" объект

Венгерская нотация

В современном программировании используется такой способ формирования имен идентификаторов. Говорят, что такой удобный и информативный способ написания имен придумал сотрудник компании Microsoft программист венгр по национальности Чарльз Симони. Суть заключается в том, что первые буквы имени являются значащими и указывают на тип переменной (константы), остальная часть - имя, идентифицирующая роль переменной в программе. Одно из удобств заключается в том, что имя переменной данного типа формируется простым отбрасыванием первых символов. Второе - не надо вспоминать, что это за переменная такая? Какого она типа? Особенно в случае, когда Вы будете придерживаться одной системы обозначений.

В Паскале часто используются два префикса: T - для идентификатора ТИПА (Type), и P - для идентификатора указателя в памяти (Pointer). Например:

TYPE
  PSomeType = ^TSomeType; {создается указатель на переменную типа TSomeType}
  TSomeType = record	        {новый тип переменной - запись с заданными полями}
    Name: String[20];
    Age   : Byte;
  end; 
В дальнейшем я буду широко пользоваться такими обозначениями. А так ... . Можно определить константу с именем constValue или cValue, которые содержат часто используемое значение переменной Value. Тогда присваивание Vakue:=cValue; выглядит и понятным и естественным.

Способы защиты переменных

В предыдущем выпуске я обещал показать, как можно, не используя объектов, отслеживать, какое значение пользователь хочет записать в мою переменную. Пожалуйста …

Существует два простых способа защиты переменной от этих пользователей: (1) размещением переменной в разделе реализаций модуля; и (2) использование типизированных констант внутри подпрограммы.

Используем свойства модулей

Исходный текст программы должен состоять из двух файлов. Первый - основной. Назовем его Main.pas. Второй файл - модуль, который назовем Prtct.pas. Ниже их текст:

Program Main;
uses 
   Crt, Prtct;
BEGIN
  SetValue(-12);
  SetValue(127);
  WriteLn('Hidden = ',GetValue);
     { Hidden:=2; }
  ReadKey
END.
unit Prtct;
interface
   procedure SetValue(AValue: Integer);
   function GetValue: Integer;
implementation
  VAR
            Hidden: Integer
procedure SetValue;
begin 
     if AValue < 0 then 
     begin 
         Writeln('Попытка записать недопустимое значение: ',AValue); Exit
    End;
    Hidden:= AValue;
end;

function GetValue: Integer;
begin
  GetValue:=Hidden
end;
END.
Запускать программу из среды разработки программа Borland Pascal нужно находясь в окне главной программы, или нужно установить "первичный файл" с помощью пункта меню Compile &right; Primary file…. Попробуйте из программу (main.pas) изменить так, чтобы прочитать, переменную Hidden. Закомментированный текст в программе и пытается делать это.

Вроде бы задача решена. Но … есть два недостатка по сравнению с объектами.

  1. Любая подпрограмма из модуля Prtct имеет доступ к этой переменной. Даже такая, которая и не задумывалась для этого. Объект пишется для решения конктерной задачи, у него не должно быть лишних методов. Модуль - это библиотека по сути своей. А в хорошей библиотеке чего только нет…
  2. Переменная занимает место в сегменте данных программы. Иногда это составляет проблему, так суммарный объем переменных и типизированных констант программы не может превысить 64 Кбайт. Объект легко разместить в динамической памяти, размер которой намного больше 64 К. То есть программа может в нужный момент загрузить экземпляр объекта в память ЭВМ. Когда он выполнит то, ради чего его писали, программа выгрузит экземпляр объекта из памяти, освободив ее для "вторичного" использования.

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

procedure WithMyVar(var PrevValue: Integer; NewValue: Integer);
const
       MyValue: Integer = 0;
begin
  PrevValue:=MyValue;
  if NewValue < 0 then begin
         Writeln('Попытка записать недопустимое значение: ', NewValue); Exit
  end;
  MyValue:=NewValue
end;
Надеюсь, протестировать работу процедуры сможете сами. А теперь обратите внимание: эта процедура имеет собственную переменную, словно объект, но объект, поверьте пока на слово, делает это элегантнее! И еще: нельзя просто прочитать значение переменной-константы MyValue. Существует "запаздывание".
[ в начало ]

Пример объекта, хранящего информацию в файле

Этот объект производит "циклическое" чтение строк из текстового файла. То есть, если файл прочитан до конца, то опять читается первая строка. Я не буду подробно комментировать код сейчас. ЭТО ВЕДЬ ИДЕЯ ООП: пользователь и не должен знать, как сложно все реализуется!

Отмечу только важное: 1) предполагается что этот код сохранен в файл B.pas. Впрочем, если не так, то только получите сообщение об ошибке; 2) в объекте есть метод, который следует вызывать самым первым procedure CallThisFirst; и есть метод, который нужно вызвать самым последним procedure CallThisLast; и нет механизма, который заставил бы пользователя сделать! А на самом деле создатели ООП предусмотрели и ЭТО!!! Но об этом в следующих выпусках; 3) этот объект в файл не пишет. Исправить несложно, но вряд ли это нужно в примере. Хотя, если кого-то заинтересует. Напишите. Покажу как это сделать.

program SecondObj;
uses  CRT;
const
  cFileName = 'B.pas';

  cmodeOk    =  0;
  cmodeFail  = -1;
  cmodeFirst =  1;
  cmodeEOF   = 10;

TYPE
  TFileString = object
  procedure CallThisFirst;
  function  First: String;
  function  Next : String;
  procedure CallThisLast;
  private
    fText: Text;
    fMode : Integer;
    procedure OpenFile(FileName: String);
  end;

procedure TFileString.CallThisFirst;
begin
  ClrScr;
  fMode:=cmodeFirst;
end;

function TFileString.First: String;
var
 Buf: string;
begin
 Buf:='';
 case fMode of
  cmodeOk   : ReadLn(fText,Buf);
  cmodeFirst: begin OpenFile(cFileName); Buf:=First end;
  cmodeFail : WriteLn('Ошибка при открытии файла');
  cmodeEOF  : begin Reset(fText); Buf:=First end;
 end;
 First:=Buf
end;

function TFileString.Next : String;
var
  Buf: String;
begin
 if fMode = cmodeOk then
    if NOT EOF(fText) then
    begin
      ReadLn(fText, Buf)
    end
    else begin fMode:=cmodeEOF; Buf:=First end;
    Next:=Buf;
end;

procedure TFileString.CallThisLast;
begin
  if fMode = cmodeOk then Close(fText)
end;

procedure TFileString.OpenFile(FileName: String);
begin
  if fMode = cModeOk then Close(fText);
  Assign(fText,FileName);
  {$I-}
  Reset(fText);
  {$I+}
  if IOResult = 0 then fMode := cmodeOk
   else fMode := cmodeFail;
end;

VAR
  F: TFileString;
  i: Integer;
BEGIN
  F.CallThisFirst;
  WriteLn(F.First);
  for i:=1 to 20 do
     WriteLn(F.Next);
  F.CallThisLast;
END.
[ в начало ]
  • Оцените "стандартный" объект

    В Borland Pascal создана система Turbo Vision. С ее помощью Вы относительно легко можете писать программы с интерфейсом, подобным интерфейсу (меню, строка статуса, система команд, окон, ...) среды разработки программ (редактор) Borland Pascal. Сейчас изучать его нет необходимости. В Delphi, например, все это делается и лучше и быстрее. (Хотя принцип тот же!). В системе Turbo Vision есть  несколько модулей, которые содержат очень полезные объекты, которые можно использовать вне системы. Например, в модуле Objects имеется объект TStringCollection, который готов для хранения коллекции строк. Сейчас я только покажу, как его использовать для хранения строк, прочитанных из файла.

    Следующий код сохранен под именем «strcol.pas». И ошибка не отрабатывается! Такое поведение естественно. Для объекта неважно, откуда берутся строки. Если для пользователя важна правильная работа в любом случае, то нужно объяснить объекту, что мы хотим от него. Дополнить его функциональные возможности. Сейчас только попробуйте.

    Вы увидите в тексте программы много новых слов. Одно интуитивно понятное слово «virtual» чего стоит! Все объяснять буду позднее - и так я до безобразия затянул работу над выпуском. Для одного сделаю исключение, для команды, которая помещает прочитанную строку в коллекцию StrCol.Insert(NewStr(S+' '));. Коллекция хранит не строки, а указатели на строки, размещенные в динамической памяти программы. Помещает их туда функция NewStr, которая плохо работает, если строка пустая. Вот я и добавляю на всякий случай пробел.

    program StrCol;
    uses CRT, Objects;
    
    TYPE
       TMyStr = object(TStringCollection)
       function Compare(Key1, Ke2: Pointer): Integer; virtual;
       end;
    
     function TMyStr.Compare(Key1, Ke2: Pointer): Integer;
     begin
       Compare:=-1
     end;
    
    VAR
       StrCol: TMyStr;
       T: Text;
       i: Integer;
       S: String;
    
    BEGIN
      Assign(T, 'strCol.pas');
      Reset(t);
      StrCol.Init(10,5);
      while NOT eof(t) do
      begin
        ReadLn(t,s);
        StrCol.Insert(NewStr(S+' '));
      end;
      for i:=0 to StrCol.Count - 1 do
         Writeln(PString(StrCol.At(i))^);
      Readkey;
      StrCol.Done;
    END.
    

    [ в начало ]

    © Борис Сурин

  • На первую страницу

    Rambler's Top100 Rambler's Top100
    PROext: Top 1000

    (с)Все права защищены

    По всем интересующим вопросам прошу писать на электронный адрес

    Hosted by uCoz