Страница 1 из 2

ООП именно в среде FreePascal[Решено]

СообщениеДобавлено: 07.04.2011 12:07:27
tech
Не могу найти описании ООП для среды FreePascal. Везде или Delphi или Lazarus.
То, что слово Class надо заменить на Object выяснено.
Теперь не получается с Constructor и созданием объектов.

Приведите, пожалуйста, пример маленькой программы для FreePascal, где есть класс и создается объект.
Или ссылки, где можно посмотреть.
Спасибо.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 07.04.2011 13:20:50
Mr.Smart
tech, читаем вот эту книжку.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 07.04.2011 14:03:24
Vadim
tech писал(а):То, что слово Class надо заменить на Object выяснено.

Не надо.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 07.04.2011 16:35:48
Maxizar
Ну запугали парня...
То, что слово Class надо заменить на Object выяснено.


Нет тут ваша БОЛЬШАЯ ошибка. Просто есть путаница мол объект это нечто общее, скажем комплексное число (Реальная часть и мнимая). И чтоб этим всем, тобишь Re и Im манипулировать как одним целым, мы для себя как программисты создаем объект. Вы скажите зачем можно писать в лоб и все такое.. можно, но я вам сейчас покажу что так легче. Во-первых нужно понимать, что когда программой будут пользоваться другие люди и извините за выражение Им наср...ть как вы там что сделали главное чтоб она работала, но вот для Вас как программиста, это имеет значение. Далее я это покажу на примере.
Так вот Объект - нечто что можна рассматривать как одно цело (объект).

Но тип определенный вами может быть Object или Class или Record. и т.п. Ну вот в C++ путанице нет у них Object или Record = Структура.. а тут просто нужно понимать в каком случае слово Объект - это сущность (Комлпексное число, Точка, прямоугольник) а в каком случае Объект = Object - Тип данных, определяемый вами. Надеюсь хоть что то встало у вас на место в голове... Ну типа тоже самое про классы:
Класс комплексных чисел, и Вчера наша команда показала Класс (Слово одно а смысл ой ой ой...).
Тоже самое и между Object и Объект.. :!: :!: :!:


Как мы можем его реализовать(В смысле это комплексное число то есть нечто, которое в нашем мире является априори одной сущностью, которым мы и хотим манипулировать и на языке как одним целостным объектом...)? Так мы можем это дело записать(реализовать) Минимум тремя способами:
1 - Создать Запись Record:
Код: Выделить всё
TComplexRecord = Record
   Re:Real;
   Im:Real;
end; 


2- Cоздать Класс: Class:
Код: Выделить всё
TComplexClass = class
   private

   public
   Re:Real;
   Im:Real;

     constructor Create;
     destructor Destroy; override;
   end; 


3 - Создать Object:
Код: Выделить всё
  TComplexObject = Object
   Re:Real;
   Im:Real;
  end;   


Далее мы сможем это дело использовать так (пример грубый но в самый раз для понимания):
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
   CR:TComplexRecord;
   CO:TComplexObject;
   CC:TComplexClass;
   S:String;
begin
   CR.Re:=1;
   S:='CR.Re='+ FloatToStr(CR.Re);

   CO.Re:=2;
   [b][/b]S:=S+' CO.Re='+FloatToStr(CO.Re);

   CC:=TComplexClass.Create;
   CC.Re:=3;
   S:=S+ ' CC.Re='+FloatToStr(CC.Re);
   Caption:=S;
end;


Теперь по порядку:
Запись – самая простая реализация и самая быстрая!!! Именно по этому работу с комплексными числами я писал через запись :)
Почему быстрая потому что это кусок памяти с которым мы обращаемся как с одним целым (как с одной сущностью, что мы как раз и хотели) Теперь нас будет компилятор ругать если что то не так…

Класс- самый большой и не поворотливый, для его инициализации мы обязательно должны вызвать конструктор (всегда) потому что именно он выделит память в куче (ОЗУ) для его экземпляра. Для нашего примера, применение класса просто не оправданно, мы не используем наследование (явно) и тем более знаем что не будем порождать от комплексного числа что то еще… По этому вся мощь классов в данном примере просто лишняя, но можно делать и так.

Объект – это запись, НО с возможностью наследования и инкапсулирования (запихивания внутрь других методов) И так же возможность создавать различные области видимости полей. (По идее это то что в Делфи называется расширенная запись, в Free Pascal есть простая запись и Объект и самое главное классы :))

Конструктор для Объектов нужен только тогда, когда будут использоваться виртуальные методы и всякая крутость… После чего он будет почти одним и тем же, что и класс, НО с той оговоркой что он будет как и запись полностью располагаться на стеке. То есть Вы передаете экземпляр комплексного числа имеющего тип Объекта (не путать просто со словом Объект обозначающий сущность чего либо) в функцию, она функция (ну компилятор если быть точным) создаст локальную копию всего числа на стеке представьте что у вас полей не два (Re and Im) а скажем сотня.. вы все поля будите копировать ( ну не вы а функция не явно при каждом вызове).. Тогда когда Вы передадите такой же функции уже переменную которая явл-ся классом, то копий создано не будет, буедт лишь передан указатель на область памяти в котором лежит ваш экземпляр (конкретное число). В этом все плюсы и минусу каждого из возможных подходов к реализации через Классы или Объекты.

В данном примере который привел я, у меня для Объектов нет конструктора! Он нам не нужен, потому что мы не используем, виртуальных методов и всяких рюшек.. И в руководстве сказано, что если ничего такого нет (виртуальных методов бла бла) мы вправе не реализовывать конструктор. Что касается классов вообще, как написано в руководстве языка Free Pascal да и других скажем Delphi, конструктор должен вызываться всегда… вы захотите опровергнуть, что мол если не задать его, а сделать что то подобное:
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
   CC:TComplexClass;
   S:String;
Begin
S:=’’;
   CC.Re:=3;
   S:=S+ ' CC.Re='+FloatToStr(CC.Re);
   Caption:=S;

end;   


То все вроде работает, Да но ходить по лезвию и пользоваться этим нельзя… Для классов всегда нужен Конструктор и для каждого Экземпляра его нужно вызвать. Именно так и написано в руководстве по FPC.

Не могу найти описании ООП для среды FreePascal. Везде или Delphi или Lazarus.


Среды FreePascal нет! Это язык программирования такой.. он так и называется Free Pascal.
описании ООП – Это один из подходов программирования, который заключается в том что мы начинаем манипулировать не битами или цифрами, а именно объектами (отдельными сущностями) скажем кнопка… Если этого бы не было, вы бы сидели и обращаясь к видеобуферу через видеокарту и т.п рисовали эту кнопку вручную (ну я грубо, так что прошу прощения у более опытных).

По этому сущность ООП можно вообще прочитать в книгах хоть по С++.

Вот Lazarus – это среда быстрой разработки, которая работает с компилятором языка Free Pascal. По этому любая книга по Лазарусу, в ней будет описан язык ФриПаскаль, и собственно ООП для этого языка. Так же подойдет любая книга по Делфи.

Просто поймите ООП – это подход, (скажем копать яму руками или лопатой и все).
Другой вопрос реализации этого подхода в языке, так вот в делфи и фрипаскале если не брать деталей все один в один, даже более того скажу в языке С++ такая же песня, там просто будут отличия в уничтожении классов при выходе из видимости переменной, автовызов конструктора и всяких рюшек….
Вам дали книгу по Паскалю, все же порекомендую вот эту, лично ее читал, так же можно прочитать это дело в DRKB.

Теперь вообще лирика: А нафига это все нужно. Элементарный пример: берем теже самые комплексные числа, мы определим их через запись (Record), после чего мы создали наш пользовательский тип, язык фрипаскаль позволяет для типа данных переопределить стандартные функции и операторы скажем + - \ * и тп. Вплоть до exp.. – этой фигней вы будете страдать один раз при их реализации… вот мой модуль содержит почти все фунции вплоть до cosh и т.п… После чего вы можете писать что то в этом роде:

Код: Выделить всё
Var A,b,c,d,;
Begin
A:= sqrt(exp(b+c) / d * sin(b+1312));
End;


А вот теперь напишите тоже самое, через решения в лоб :twisted: , у вас будет для каждого числа Re и Im части. Откройте любой справочник по матану, и посмотрите как реализуется скажем деление… Вы скажите но ведь когда Мы будем переопределять все это дело при перегрузке операторов и функций будем делать тоже самое. Да НО мы это делать будем один раз ОДИН.. после этого мы будем писать как нормальные люди, как в Маткаде...

Ну думаю понятно объяснил :oops: :oops: ... про классы более подробно можно прочитать в любой нормальной книге, поверте если в книге написано не понятно или сложно про классы, поверте Автор ... и просто не берите эту книгу... :!:

PS. Так же подобные вещи обсуждались ТУТ(более внимательно читаем Ответы Сергея Горелкина :!: )

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 11:52:44
vada
Объектами и классами ворочаю уже больше 20 лет, но более внятного, доходчивого и краткого описания еще не встречал!!!!
Уважаемый Maxizar, вам бы книжки писать. Я серьезно.

Добавлено спустя 4 минуты 23 секунды:
Кстати, направлять к С++ как к источнику высших знаний, я бы поостерегся. Более путаный язык еще поискать. Лучше JAVA. Правда там Объект это экземпляр Class-а :)

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 11:58:16
tech
Требуется написать ООП-программКУ без графического интерфейса. Не нужны никакие кнопки и лишний код. Чисто демонстрация основных концепций ООП для учащихся 14-15 лет. Ничего лишнего и заумного. Назначение всех строчек кода должно быть ясно и понятно. Когда я выбираю "консольное приложение" в Lazarus, там появляется "куча кода". Поэтому пытаюсь написать во FreePascal. Информация о создании классов и их конструкторов смотрелась в книжках по Паскалю. Не получается.

Код: Выделить всё
type myclass = object {Если написать class, то не работает}
    a,b: byte;
    procedure print;
end;

{??? - КАК СОЗДАТЬ КОНСТРУКТОР КЛАССА}

{constructor myclass.create(a,b);         как в Delphi
begin a:=a; b:=b end;
end;}

{constructor myclass.init;                    как в Turbo
begin a:=c; b:=d end;
end; }

procedure myclass.print;
begin  writeln(a); writeln(b) end;

var obj: myclass;

begin
    {??? - КАК СОЗДАТЬ ОБЪЕКТ}

    writeln('­ Нажмите Enter');
readln;
end.

Исправьте, пожалуйста, кто-нибудь этот пример, чтобы создавался объект.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 12:18:32
Mr.Smart
Видимо плохо читали или не внимательно. В книге, на которую я скинул ссылку всё это разжёвано.
Код: Выделить всё
type

  pmyclass = ^myclass;
  myclass = object
     a,b: byte;
     procedure print;
     constructor Init(c,d: Byte);
end;

constructor myclass.init(c,d: Byte);
begin
  a:=c;
  b:=d;
end;

procedure myclass.print;
begin
  writeln(a);
  writeln(b)
end;

var obj: pmyclass;

begin
   obj:=new(pmyclass,init(1,2));
   obj.print;
   dispose(obj,done); 

    writeln(' Нажмите Enter');
readln;
end.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 12:20:41
daesher
tech писал(а):Требуется написать ООП-программКУ без графического интерфейса. Не нужны никакие кнопки и лишний код. Чисто демонстрация основных концепций ООП для учащихся 14-15 лет. Ничего лишнего и заумного. Назначение всех строчек кода должно быть ясно и понятно. Когда я выбираю "консольное приложение" в Lazarus, там появляется "куча кода". Поэтому пытаюсь написать во FreePascal.

Не обязательно: в Lazarus есть вариант "Программа". А лишний код можно и удалить.


Код: Выделить всё
{$ifdef fpc}{$mode objfpc}{$endif}//теперь все классы будут работать
{$ifdef MSWINDOWS}{$apptype console{$endif}//Теперь приложение точно будет консольным
uses Classes;
type myclass = class(TObject)
    a,b: byte;
    procedure print;
    constructor Create(a,b:byte);
end;

{??? - КАК СОЗДАТЬ КОНСТРУКТОР КЛАССА - очень просто, только нельзя забывать его определить в описании класса}

constructor myclass.create(a,b:byte);//         как в Delphi - а какая здесь разница?
begin
Inherited Create;//Не забываем!
a:=a; b:=b
end;


{constructor myclass.init;                    как в Turbo -  Можно и так, тогда надо оставить object(...)
begin a:=c; b:=d end;
end; }

procedure myclass.print;
begin  writeln(a); writeln(b) end;

var obj: myclass;

begin
    {??? - КАК СОЗДАТЬ ОБЪЕКТ}
   Obj:=MyClass.Create(2,3);
   Obj.print;
  Obj.Free;
    writeln('­ Нажмите Enter');
readln;
end.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 12:26:37
Vadim
daesher писал(а):type myclass = class(TObject)

Полностью согласен с докладчиком на счёт этого варианта создания класса. ;)

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 12:31:00
Odyssey
Как уже написал daesher, чтобы создать простую программу без графического интерфейса и без обработки командной строки в Lazarus, лучше выбирать "Программа" (Program). Тогда код получится примерно такой:
Код: Выделить всё
program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };

{$R *.res}

begin
end.

Из него можно смело убрать cthreads, если не нужна поддержка потоков, и комментарии. Ещё в параметрах проекта можно убрать значок программы и удалить ссылку на файл ресурсов. Если не пользуемся какими-нибудь классами из стандартной библиотеки, типа TStringList, можно убрать uses Classes. Тогда получится что-то типа:
Код: Выделить всё
program Project1;
{$mode objfpc}{$H+}
begin

end.

Если сильно мешает {$mode objfpc}{$H+} можно убрать и её, но тогда нужно убедиться, что в настройках проекта включено:
1) "Параметры компилятора" - "Режим синтаксиса (-M)" - "Object Pascal - по умолчанию (-Mobjfpc)"
2) "Параметры компилятора" - "Использовать строки Ansi (-Sh)".

Ошибки в вашем коде с class связаны скорее всего с тем, что консольная FP IDE устанавливает режим по умолчанию "fpc", а для классов нужен "objfpc" или "delphi". В Lazarus по умолчанию - "objfpc". Т.е. чтобы заставить классы работать в консольной IDE можно указать в исходниках {$mode objfpc} или {$mode delphi}.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 12:38:07
vada
Код: Выделить всё
type myclass = class(TObject)

Чёта я очкую, Славик. Думаешь прокатит?

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 12:40:39
tech
Спасибо. Буду разбираться.

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 16:54:44
Maxizar
vada писал(а):Объектами и классами ворочаю уже больше 20 лет, но более внятного, доходчивого и краткого описания еще не встречал!!!!
Уважаемый Maxizar, вам бы книжки писать. Я серьезно.

Ой Спасибо :oops: :oops: Возможно я когда нибудь задумаюсь над этим, просто Вы не первый кто мне об этом говорит, возможно у меня и правда получится... :D

Что касается С++ ну я просто не знаком с Java :evil: .

tech писал(а):Спасибо. Буду разбираться.

Если вопрос, для вас решен, то если не затруднит добавьте в заголовок темы (название темы) [Решено] Для этого нужно отредактировать самое первое сообщение нажав кнопочку правка... и изменить название темы (Старое название)+ ' [Решено] ';

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 22:52:27
tech
Maxizar писал(а):Если вопрос, для вас решен, то если не затруднит добавьте в заголовок темы (название темы) [Решено] Для этого нужно отредактировать самое первое сообщение нажав кнопочку правка... и изменить название темы (Старое название)+ ' [Решено] ';

В принципе "да": чистый рабочий код получен. Правда только в Lazarus, хотя тут он даже выглядит нагляднее. Остался спортивный интерес: почему не работает во FreePascal?

Выше были приведены две варианта синтаксиса ООП на паскале. На картинке ниже убрано все "лишнее" и закомментирована нерабочая часть кода. В таком виде оба скрипта прекрасно выполняются в Lazarus, а первый еще и во FreePascal.
Изображение
  • [прог.1]Если раскомментировать строку obj.print, то выдается ошибка Illegal qualifier (неправильный спецификатор) - и в Lazarus и во FreePascal.
  • [прог.1]Если раскомментировать строку dispose(obj,done);, то выдается ошибка expression must be destructor call (выражение должно быть вызовом деструктора) - и в Lazarus и во FreePascal. Но если записать вот так - dispose(obj) - то работает.
  • [прог.2]Работает в Lazarus и не работет во FreePascal. В последнем ругается на слово class: identifier not found "class" (идентификатор "class" не найден).

Re: ООП именно в среде FreePascal

СообщениеДобавлено: 08.04.2011 23:43:17
Mr.Smart
Ах да. В случае ООП в стиле Borlad Pascal.
Код: Выделить всё
obj^.print; { необходимо разименовать указатель }

В данном случае деструктор не реализован в объекте т.ч.
Код: Выделить всё
Dispose(obj);