Помощь - Поиск - Пользователи - Календарь
Полная версия: ООП во FP
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Free Pascal, Pascal ABC и другие
Страницы: 1, 2
compiler
вот какой вопрос возник(словами не получается попробую на примере)
дано 3 объекта(одного типа M с двумя полями- днем и месецем.) необходимо прочитать данные для первых 2-х объектов(это я сам сделаю) и ввести разницу дат в 3-ий объект(как).

примечание
первый и второй объект являются родительскими для третьего.
Помогите.. Собственно у меня все получается кроме обработки данных

интересно было бы увидеть реализацию и на TP.
volvo
Цитата
первый и второй объект являются родительскими для третьего.
Вот с этого места - подробнее... Это как понимать? ОБА сразу? Или тип, к которому относятся И первый И второй объекты (то, есть, они принадлежат к одному типу) - родительский для типа третьего?

Цитата
Собственно у меня все получается кроме обработки данных
Описания типов - в студию...
compiler
Цитата(volvo @ 22.04.2007 16:47) *
Вот с этого места - подробнее... Это как понимать? ОБА сразу? Или тип, к которому относятся И первый И второй объекты (то, есть, они принадлежат к одному типу) - родительский для типа третьего?

или
Цитата(volvo @ 22.04.2007 16:47) *
Описания типов - в студию...


fraction = object
num,
den:integer;

constructor init;
procedure reduction;
end;

FrRes =object(fraction)
procedure print;
end;
{...методы...}
var
f1,
f2:fraction;
FRes:FrRes;


а вот текст всей программы для которой необходима эта теорияНажмите для просмотра прикрепленного файла
мисс_граффити
Цитата
Или тип, к которому относятся И первый И второй объекты (то, есть, они принадлежат к одному типу) - родительский для типа третьего?

не получается так:
Цитата
дано 3 объекта(одного типа M с двумя полями- днем и месецем.)
compiler
Цитата(мисс_граффити @ 22.04.2007 16:59) *
не получается так:
кажется я всех запутал. текст программы "в студии".
мисс_граффити
так?
procedure FrRes.subtract(const f1,f2: fraction);
begin
num:=f1.num*f2.den-f2.num*f1.den;
den:=f1.den*f2.den;
end;
volvo
compiler, вот я не понимаю, зачем тебе ЗДЕСЬ наследование? Просто, чтоб было? Не надо оно тебе... Вот так:

{$mode objfpc}

type
fraction = object
num, den: integer;

constructor create;
constructor init;

procedure reduction;
procedure print;
end;


constructor fraction.create;
begin end;

constructor fraction.init;
begin
read(num, den);
reduction;
end;

procedure fraction.reduction;
var
a,b,nod:integer;
begin
a:=num;
b:=den;
while (a <> 0) and (b <> 0) do
if a >= b then a := a mod b
else b := b mod a;

nod := a + b;
num := num div nod;
den := den div nod;
end;

procedure fraction.print;
begin
write(num, ' / ', den);
end;

var
f1, f2: fraction;

operator - (const first, second: fraction) the_result: fraction;
begin
the_result.create;

the_result.den := first.den * second.den;
the_result.num := first.num * second.den - second.num * first.den;
the_result.reduction;
end;


begin
f1.init;
f2.init;

(f1 - f2).print;
readln;
end.



Welcome to FPC smile.gif
compiler
2 мисс_граффити ,наверно то но как собственно вызывать эту процедуру?(+ както она у меня не работает на FP)

2 volvo , спасибо за приглашение но без твоих комментариев мне будет не легко... (зачем собственно деректива в первой строчке? остальное вроде понял..)
наследование было по двум причинам
1 потому что первые две дроби печатать не надо..
2 что б было (в смысле в учебных целях)
мисс_граффити
1. эта цель - она не цель smile.gif
разве обязательно использовать ВСЕ методы, которые есть?

2. так и думала...

Цитата
наверно то но как собственно вызывать эту процедуру?

f1.init;
f2.init;
f1.reduction;
f2.reduction;

FRes.subtract(f1,f2); //вот
FRes.reduction;
FRes.print;


operator - (const first, second: fraction) the_result: fraction;

good.gif
compiler
как задать константу у обьекта/класса?
заранее благодарен.
volvo
Зачем это тебе, расскажи ...
мисс_граффити
Разработчики Java так любят делать, по-моему.
Определили в классе Double константы +бесконечность и -бесконечность, например...
hardcase
Константы?
Насколько я знаю такие экземпляры классов называются синглтоны.
Нужно завести статическое поле/свойство в классе и при чтении возвращать объект, который создается единственный раз при инициализации класса (в нашем случае юнита, где находится класс).
volvo
Цитата
Нужно завести статическое поле/свойство в классе
Можно код для FPC? (вопрос был именно про FPC, так что все сотрясания воздуха о своей крутизне в C#/Java/... можешь оставить при себе для более подходящих случаев dry.gif )
hardcase
Цитата(volvo @ 24.06.2007 0:47) *
Можно код для FPC? (вопрос был именно про FPC, так что все сотрясания воздуха о своей крутизне в C#/Java/... можешь оставить при себе для более подходящих случаев dry.gif )

Возможно вот так....
Код

interface

    TMyClass = class
    private
        class function GetSingletonObject: TMyClass;
    public
        class property SingletonObject: TMyClass read GetSingletonObject;
    end;
    
implemetation

var
    _SingletonObject: TMyClass;

class function TMyClass.GetSingletonObject: TMyClass;
begin
    Result := _SingleTonObject;
end;

initialization
    _SingletonObject := TMyClass.Create;
    //...дополнительная инициализация....

finalization
    _SingletonObject.Free;
compiler
Цитата(volvo @ 23.06.2007 19:01) *
Зачем это тебе, расскажи ...
мне надо реализовать карту как обьект при этом мне могут понадобится границы... хотя наверное и не понадобится... или понадобится smile.gif ну а потом для общего развития.


Добавлено через 1 мин.
Цитата(hardcase @ 24.06.2007 0:44) *
Возможно вот так....
а можно комментарии...
volvo
В FPC нет понятия class property... Функция/процедура есть, а свойства - нет... Так что как минимум:

type
TMyClass = class
private
class function GetSingletonObject: TMyClass;
public
property SingletonObject: TMyClass read GetSingletonObject;
end;



кстати, кто мне объяснит, к поставленной задаче, каким боком вообще относится синглтон? Кто-то просил объект, число экземпляров которого ограничено одним (это - синглтон)? Я не заметил этого...

compiler, константы не могут описываться внутри класса... Описывай их в Implementation-части модуля, а для обращения к ним - используй class function...
compiler
я чего то туплю.... ничего не понимаю...
volvo
Что непонятно? Ну, вот, скажем:

unit z;

interface

type
T = class
private
function GetMaxSize: integer;
public
property maxSize: integer read GetMaxSize;
end;

implementation

const
the_max_size = 20;

function T.GetMaxSize: integer;
begin
result := the_max_size;
end;

end.


uses z;

var
obj: T;

begin
obj := T.create;
writeln(obj.maxSize);
end.

Что будет напечатано?

А теперь попробуй получить доступ к the_max_size НЕ через maxSize... То есть, эффект совершенно аналогичен тому, как если бы константа была описана в самом классе...
compiler
кажется понял, спасибо...

с меня +

Добавлено через 3 мин.
и еще вопрос... можно ли для класса описать сравнение с нулем?
volvo
Цитата
можно ли для класса описать сравнение с нулем?
Это смотря что ты хочешь сравнивать с нулем... То есть, что (для твоего класса) значит равенство нулю?

Для объекта можно было бы также переопределить "operator =", сравнивающий экземпляр объекта с целым числом, например... Для классов перегрузка операций проблематична.
мисс_граффити
сорри, FPC у меня нет, проверить могу только в делфи. но идея, наверное, понятна:
  T=class
a,b: integer;
function isNull: boolean;
end;
...
function T.isNull: boolean;
begin
isNull:=(a=0)and(b=0);
end;

compiler
через метод не так интересно... интересно было бы именно перегрузкой операторов...
что б можна было скажем написать
...if a<>0 then ...
, где а -- пользовательский тип, имеющий два поля целых чисел, и равнявшийся нулю, если оба поля равны нулю...
volvo
В таком случае (если у тебя 2 поля должны быть одновременно нулевыми чтобы объект считался нулевым) тебе лучше перегрузить оператор not:

{$mode ObjFpc}
type
T = object
a, b: integer;

constructor init(va: integer = 0; vb: integer = 0);
end;

operator not (const X: T): boolean;
begin
result := (X.a = 0) and (X.b = 0);
end;

constructor T.init(va: integer; vb: integer);
begin
a := va; b := vb;
end;

var
obj: T;
begin
obj.init();
writeln(not obj);

obj.a := 9;
writeln(not obj);
end.

compiler
Цитата(volvo @ 25.06.2007 14:08) *
В таком случае (если у тебя 2 поля должны быть одновременно нулевыми чтобы объект считался нулевым) тебе лучше перегрузить оператор not...
идея интересная, но мне понадобится сравнивать и с другими числами(по крайней мере еще с одним)...
Цитата
Для классов перегрузка операций проблематична.
а где про нее можна прочитать?
volvo
Цитата
идея интересная, но мне понадобится сравнивать и с другими числами
Ты бы уточнял, ЧЕГО ты хочешь? Либо КАЖДОЕ поле сравнивать с ОДНИМ И ТЕМ ЖЕ числом
(тогда - вот так:
operator = (const X: T; const i: integer): boolean;
begin
result := (X.a = i) and (X.b = i);
end;
...
// тестируем:
obj.init(3, 3);
writeln(obj = 3);

obj.a := 9;
writeln(obj = 9);
...


)

, либо (что в конце концов тебе выяснится, тебе и было нужно) каждое поле - с РАЗНЫМ числом...

Цитата
а где про нее можна прочитать?
Нигде нельзя... Попробуй то же самое сделать для Class-а, а не для Object-а, получишь ошибку компиляции... Для Object-ов и Record-ов все прекрасно работает...
compiler
Цитата(volvo @ 25.06.2007 15:55) *

Либо КАЖДОЕ поле сравнивать с ОДНИМ И ТЕМ ЖЕ числом, либо (что в конце концов тебе выяснится, тебе и было нужно) каждое поле - с РАЗНЫМ числом...
пока достаточно с одним...

посижу подумаю...
compiler
Добрый день!
У меня есть вопрос, мне надо перегрузить оператор присваивания...
у меня он должен заключаться в следующем
1) присваивания между обьектами одного класса происходит стандартно(выражение слева приобретает выражение справа)
2) возможно когда выражение справа есть некий символ (а еще лучше если можно было бы использовать строку)
тоесть есть класс направление (содержащий два поля -- x, y.). если я пишу
 direction:='left';
, тогда должно происходить следующее
direction.x:= -1; direction.y:=0;
.
Заранее благодарен.

Добавлено через 3 мин.
и еще, нельзя ли использовать различные методы сравнения(в смысле перезагруженные операторы сравнения) в зависимости от передаваемых параметров?
volvo
{$mode objfpc}
type
dir = (left, right, up, dn);
T = object
x, y: integer;
procedure print;
end;

procedure T.print;
begin
writeln('X: ', x, ' Y: ', y);
end;

const
p: array[dir] of record
s: string;
px, py: integer;
end =
(
(s:'left' ; px:-1; py: 0),
(s:'right'; px: 1; py: 0),
(s:'up' ; px: 0; py:-1),
(s:'dn' ; px: 0; py: 1)
);


operator := (const d: dir): T;
begin
with result do begin
x := p[d].px; y := p[d].py;
end;
end;

operator := (const s: string): T;
var i: dir;
begin
result.x := 0; result.y := 0;

for i := low(dir) to high(dir) do
if p[i].s = s then
with result do begin
x := p[i].px; y := p[i].py;
end;

end;

var
x: T;

begin
x := 'left';
x.print;

x := 'right'; // <--- Здесь - работаешь со строкой
x.print;

x := up; // <--- А тут - с перечислимым типом
x.print;
end.



Цитата
нельзя ли использовать различные методы сравнения(в смысле перезагруженные операторы сравнения) в зависимости от передаваемых параметров?
Можно, только для этого должны перегружаться операторы для сравнения данных разных типов... Например, так:
// Тут твой тип будет сравниваться с целым числом
operator < (x: T; i: integer): boolean;
begin
// ...
end;
// А тут - со вторым значением такого же типа
operator < (x: T; i: T): boolean;
begin
// ...
end;

compiler
Огромное спасибо! но у меня есть пару вопросов, может некоторые прямо не касающееся темы...
Цитата(volvo @ 2.07.2007 19:16) *


type
dir = (left, right, up, dn); // ? dir это множество?
T = object
x, y: integer;
procedure print;
end;

const
p: array[dir] of record//???
s: string;
px, py: integer;
end = //?
(
(s:'left' ; px:-1; py: 0),
(s:'right'; px: 1; py: 0),
(s:'up' ; px: 0; py:-1),
(s:'dn' ; px: 0; py: 1)
);
оperator := (const d: dir): T; //вот это здорово!
//а то я делал по аналогии со сравнением,
//приходилось описывать возращаемый результат
//и 2 получаемых(правильный термин?)...



еще раз спасибо!
volvo
1.
Цитата
dir это множество?
Нет, это перечислимый тип.

2. Непонятен способ описания константы? Смотри, есть 2 способа. Можно сделать так:
type
myrec = record // сначала опишем саму структуру (вернее, ее тип)
s: string;
px, py: integer;
end;
const
p: array[dir] of myrec = ... // Описываем массив из этих структур


Но ведь, если мне больше нигде не нужно описание типа myrec (ну не собираюсь я его использовать больше в программе), то я могу определить этот тип прямо в описании константы. И теперь вступает в силу вот такое ограничение: я собственно тип "запись" нигде использовать не могу (поскольку он безымянный), а обращаться к полям записи через элемент массива - пожалуйста. Что и делается...

А array[dir] - собственно, создается массив такой длины, сколько элементов существует в перечислимом типе dir... То есть, приведенное выше объявление эквивалентно:

const
p: array[low(dir) .. high(dir)] of record ...

или даже
const
p: array[left .. dn] of record ...


Но я бы все-таки не рекомендовал пользоваться последним описанием, очень велика вероятность нарваться на ошибку, которую при первом описании ты не совершишь никогда (она будет поймана еще на этапе компиляции).
compiler
Цитата(volvo @ 4.07.2007 17:55) *
1. Нет, это перечислимый тип.
а где про него можна почитать? И чем он отличается от множества?

остальное вроде ясно.

спасибо!
volvo
Перечислимые типы
сравни с:
Множественные типы

Цитата
И чем он отличается от множества?
Ну, допустим, тем что множество - это набор значений некоего базового типа, а перечислимый тип определяет совершенно новый тип, никак не связанный ни с одним из уже существующих...
compiler
с горем пополам вроде понл
Цитата(volvo @ 4.07.2007 18:11) *
совершенно новый тип, никак не связанный ни с одним из уже существующих...
а вот это заинтересовало... можем ли мы с нуля создать свой integer
volvo
Нет... Во всяком случае - с помощью перечислимых типов - нет. Элементы таких типов должны быть правильными идентификаторами, а ты хочешь, чтобы тип содержал числа, так? Число правильным идентификатором не является.

Кроме всего прочего есть ограничение на размер перечислимых типов - 256 элементов. Integer побольше будет, я думаю...
compiler
а вообще возможно ли такое реализовать(именно с нуля)?
volvo
А зачем? У тебя же есть уже Integer, зачем второй тебе? Ладно бы, задумал реализовать Int256 или Int1024, например, чтоб с длинными числами работать (кстати, уже было на форуме. Как-то для Aelita я делал подобную реализацию Int256)... Можно, например, реализовать так же, как в "Длинной арифметике", только ограничить количество элементов массива.

Перегрузка операций есть, значит, с переводом (строка -> число) и (число -> строка) проблем не будет. Сравнение элементов нового типа - тоже не проблема... Все реализуемо...
compiler
Цитата(volvo @ 4.07.2007 19:20) *
А зачем?
когда-то хотел ради интереса, но практического применения не нашел... хотя нет, если я захочу сделать свой компилятор( lol.gif ), мне может это понадобится... но оставим это на потом...
compiler
двигаюсь дальше появляются новые ошибки... в этот раз
Цитата
Only static variables can be used in static methods or outside methods
в методе
function getXMax():integer; //public
begin
getXMax:=high (map.a); //public a: array[0..10, 0..10] of integer;
end;
что делать?
volvo
map это у тебя что? Не имя ли объекта? Если так, то нельзя обращаться к матрице в НЕклассовом методе через map.a, достаточно написать просто:

function getXMax(): integer;
begin
result := high(a);
end;
compiler
тут я разобрался, но у меня возникают проблемы при размещении обьекта в модуле
берем программу volvo приабразовываем в модуль(прикрепленный файл) и аналогичном тесте получаю Error:
Код
test.PAS(6,8) Error: Incompatible types: got "ShortString" expected "T"
test.PAS(9,8) Error: Incompatible types: got "ShortString" expected "T"
test.PAS(12,8) Error: Incompatible types: got "dir" expected "T"
почему?

заранее благодарен.
volvo
Цитата
почему?
Потому, что у тебя программа не знает о переопределении в модуле оператора присваивания, ей надо об этом сообщить... Добавь в модуле перед Implementation описания:

operator := (const d: dir): T;
operator := (const s: string): T;

, и все будет компилироваться.
compiler
спасибо!

А можна где нибудь посмотреть пример вызова метода другого обьекта(который описан в другом модуле) из метода другого обьекта(который также реализован в отдельном модуле)?

заранее благодарен.

Добавлено через 3 мин.
у меня возникает Class isn’t a parent class of the current class
volvo
Можно посмотреть пример, как ты это делаешь?
compiler
Цитата(volvo @ 8.07.2007 20:27) *
Можно посмотреть пример, как ты это делаешь?
{$mode objfpc}
unit e1;
interface
type
o1 = object
procedure p();
end;
implementation
procedure o1.p();
begin end;
end.
и
{$mode objfpc}
unit e2;
interface
type
o2 = object
constructor create;
procedure pr();
end;
implementation
uses e1;
procedure o2.pr();
begin o1.p();end;
end.



volvo
Ты пытаешься вызвать процедуру через тип объекта, а для этого надо static метод... В FPC нереализуемо, если у тебя o1 является Object-ом, а не Class-ом... С Class-ом будет так:

{$mode objfpc}

unit e1;
interface

type
o1 = class
class procedure p();
end;

implementation

procedure o1.p();
begin end;

end.


, тогда


procedure o2.pr();
begin
o1.p(); // здесь - Ok
end;



Ну, а на самом деле я думаю, что тебе надо бы объявить экземпляр объекта типа o1, и вызывать для него метод P:

var
ex1: o1;
procedure o2.pr();
begin
ex1.p();
end;

compiler
м-да...
Цитата(volvo @ 8.07.2007 21:19) *
Ты пытаешься вызвать процедуру через тип объекта, а для этого надо static метод...
тоесть если я сделаю все static оно может заработает но не на FPC smile.gif
Цитата(volvo @ 8.07.2007 21:19) *
В FPC нереализуемо, если у тебя o1 является Object-ом, а не Class-ом...
ух єти классы.. где про них можна прочитать(руководство смотрел только больше запутался и вообще потерял способность различать обьекты и классы оф. сайт FP, моя тема...)
Цитата(volvo @ 8.07.2007 21:19) *
Ну, а на самом деле я думаю, что тебе надо бы объявить экземпляр объекта типа o1, и вызывать для него метод P:
в том же и дело что это только модули подключаемые к программе...

ЗЫ попробую через классы...
ЗЗЫ хотелось бы услышать твое обьяснение о различии обьектов и классов...

volvo
Цитата
хотелось бы услышать твое обьяснение о различии обьектов и классов...
Того, что есть в документации (prog.pdf, chapters 8.2.12/8.2.13) недостаточно?
compiler
Цитата(volvo @ 9.07.2007 12:50) *
Того, что есть в документации (prog.pdf, chapters 8.2.12/8.2.13) недостаточно?
Class ... just like objects...smile.gif
volvo
Ну, отличий тоже хватает:

1) (там же - 8.2.13)
Цитата
Contrary to objects, all data fields of a class are always stored in heap memory.


Дальше - из ref.pdf:
2)
Цитата
6.3.2 Virtual methods
Classes have virtual methods, just as objects do. There is however a difference between the two. For objects, it is sufficient to redeclare the same method in a descendent object with the keyword virtual to override it. For classes, the situation is different: virtual methods must be overridden with the override keyword. Failing to do so, will start a new batch of virtual methods, hiding the previous one.

3) Добавлены message methods для классов ...
4) Уровень доступа published

+ еще одно отличие: operators overloading прекрасно работает с Object-ами, но с Class-сами происходят очень непонятные вещи...

Цитата(compiler)
в том же и дело что это только модули подключаемые к программе...
Ну и что, что только модули? Если модуль, так можно бессмысленно писать что-то? Что ты думаешь будет делаться в этом фрагменте:
  o1.p();
? Особенно, если ни один экземпляр класса (или объекта) еще не инстанцирован?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.