Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.03.28;
Скачать: CL | DM;

Вниз

Как определять абстрактные методы?   Найти похожие ветки 

 
BPK   (2004-03-09 14:24) [0]

Существует класс:

 TMyAbstract=class
 protected
   FList:TList;
   function GetItem(Num:integer):TCustomRecord;
   procedure SetItem(Num:integer; OfmRec:TCustomRecord);
   function GetItemsCount:integer;
 public
   function AddItem(OfmRec:TCustomRecord):integer;
   procedure DeleteItem(Num:integer);
   property Items[Num:integer]:TCustomRecord read GetItem write SetItem; default;
   property ItemsCount:integer read GetItemsCount;
   procedure Clear;
   procedure CopyFrom(SL:TMyAbstract);
 end;

Теперь представьте, что из него нужно сделать абстрактный класс, т.е. методы GetItem, SetItem, AddItem, DeleteItem, Clear, CopyFrom,
а также свойство Items
должны стать абстрактными.

С методом Clear никаких проблем нет, а вот с остальными - загвоздка.

Проблема заключается в том, что тип, замещённый мною для наглядности словом "TCustomRecord" будет определён только в классах-потомках. Известно только то, что это во всех случаях будет структура (record).

Вторая проблема в том, что для методов-функций нужно указать тип возвращаемого результата, а он опять-таки не определён.

Третья проблема: в свойстве Items тоже применяется тот же самый тип (т.е. как указать, что Items, GetItem и SetItem имеют один и тот же общий тип данных, но пока он неизвестен?)

И ещё: существует ли такое понятие, как абстрактное свойство? Если да, то как его объявлять?


 
Тимохов ©   (2004-03-09 14:27) [1]

вместо TCustomRecord используйте:
либо все-таки класс, либо просто pointer и в потомках переопределяйте методы с явным приведением типа.


 
YuRock ©   (2004-03-09 14:30) [2]

Для методов директивы "virtual; abstract" должны помочь

> абстрактное свойство
Встречал только разве-что если оно определено через read/write абстрактные методы.


 
BPK   (2004-03-09 14:32) [3]

>Для методов директивы "virtual; abstract" должны помочь

Да я не об этом. Я спрашиваю: значит ли это, что вместо неизвестного типа данных в абстрактных методах можно подставлять совершенно любой тип из числа определённых на текущий момент?


 
Тимохов ©   (2004-03-09 14:34) [4]


> BPK   (09.03.04 14:32) [3]

Говорю же - пользуйтесь pointer и приводите тип к какому захотите в потомках.

Явно, то о чем вы справшиваете, в дельфи нет.


 
BPK   (2004-03-09 14:34) [5]

>Встречал только разве-что если оно определено через
>read/write абстрактные методы

А как указывать неизвестный тип свойства?


 
Тимохов ©   (2004-03-09 14:35) [6]

никак


 
BPK   (2004-03-09 14:36) [7]

>никак

т.е. даже не через pointer, а вообще ничего не писать?


 
BPK   (2004-03-09 14:39) [8]

Если вообще ничего не писать, то ругается.


 
YuRock ©   (2004-03-09 14:39) [9]

> А как указывать неизвестный тип свойства?

Пусть есть переменная varObj: TObject

Попробовать узнать ее настоящий тип можно, например, такими путями:
1. if varObj.ClassName = "T_Неизвестный_тип" then ...;
2. if varObj.ClassType = T_Неизвестный_тип then ...;
...


 
Тимохов ©   (2004-03-09 14:39) [10]


> т.е. даже не через pointer, а вообще ничего не писать?

не понял фразу.


 
YuRock ©   (2004-03-09 14:41) [11]

> вместо неизвестного типа данных в абстрактных методах можно подставлять совершенно любой тип из числа определённых на текущий момент?

Если это объект - конечно надо TObject "подставлять"


 
BPK   (2004-03-09 14:41) [12]

>> т.е. даже не через pointer, а вообще ничего не писать?

>не понял фразу.

Т.е.
property Items[Num:integer] read GetItem write SetItem; default;


 
BPK   (2004-03-09 14:42) [13]

>Если это объект - конечно надо TObject "подставлять"

А если record?


 
Тимохов ©   (2004-03-09 14:44) [14]


> BPK   (09.03.04 14:42) [13]

Ну вы и упертый :))))0
Если record, то кроме как через pointer хорошо не сделаете.


 
YuRock ©   (2004-03-09 14:44) [15]

> BPK   (09.03.04 14:41) [12]

Пусть GetItem будет возвращать TObject, а у SetItem будет параметр Value: TObject


 
YuRock ©   (2004-03-09 14:45) [16]

Извините, я слово record только щас заметил


 
YuRock ©   (2004-03-09 14:47) [17]

А в чем с record проблема? Определить тип, конечно, неудастся (это вообще нонсенс - тип структуры :)), только размер разве-что...


 
BPK   (2004-03-09 14:49) [18]

Спасибо. Всё уразумел. Буду писать pointer. Вообще, как я понял, там всё равно какой тип указывать, лишь бы этот тип был определён.
Всё равно определение метода поменяется.
Просто меня немного смутили объявления в модуле Classes такого рода:

function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
function Write(const Buffer; Count: Longint): Longint; virtual; abstract;

Заметьте: здесь тип параметра Buffer не указан.

>Ну вы и упертый
Нет, я не упёртый. Это был диалог с YuRock.


 
Тимохов ©   (2004-03-09 14:52) [19]


> BPK   (09.03.04 14:49) [18]

Тип buffer не указан, т.к. это по сути тот же pointer, только описанный неявно (синтаксис немного другой), а так, тот же pointer.


 
BPK   (2004-03-09 18:58) [20]

А вот Вам и ошибочка: не получается.

TAbstractItem=pointer;

TItemsList=class
private
 ...
 function GetItem(Num:integer):TAbstractItem; virtual; abstract;
 ...
public
 ...
end;

TOfmList=class(TItemsList)
private
 ...
 function GetItem(Num:integer):TOfmRecord; override;
 ...
public
 ...
end;

Пишет:
Declaration of "GetItem" differs from previous declaration.
А у меня нет возможности чётко указать тип данных, возвращаемых функцией абстрактного класса.


 
Тимохов ©   (2004-03-09 19:00) [21]

А на фига вам virtual?
Что вы собираетесь добиться через такую конструкцию?
Мне сложно представить :)))))


 
Тимохов ©   (2004-03-09 19:03) [22]

Имхо вы рановато взялись за абстракцию.
Все-таки немного знаний ооп в дельфи не хватает.

Вы вообще чего хотите добится?


 
icWasya ©   (2004-03-09 19:13) [23]

человек хочет сделать Сишный vector<TAbstractItem>
надо объяснить, чтобы и не пытался


 
Тимохов ©   (2004-03-09 19:16) [24]


> надо объяснить, чтобы и не пытался

потом рождаются легенды, что дельфи плохой язык :(((((


 
YuRock ©   (2004-03-09 19:23) [25]

> icWasya ©   (09.03.04 19:13) [23]
> человек хочет сделать Сишный vector<TAbstractItem>

Что он хотел сделать? Что это за "function GetItem(Num:integer):TOfmRecord; override;"????

Что override? То, что в базовом классе privat? Что, Си позволяет перекрывать privat?


 
YuRock ©   (2004-03-09 19:26) [26]

Вообще мне нравится! Делать абстрактные методы недоступными для наследников! А виртуальные - с разными типами параметров - тоже хороший стиль... Как себя комписятор поведет? Тяжело сказать...


 
Матлабист   (2004-03-09 19:32) [27]

Посмотри, как сделаны коллекции в Classes... Они не подойдут?


 
Defunct ©   (2004-03-09 19:40) [28]

> Что override? То, что в базовом классе privat? Что, Си позволяет перекрывать privat?

Какая разница что перекрывать? Private секция определяет только область видимости функции. Вообще совет избавиться от Record, работать только с классами.

TMyAbstratctClass = Class(_)
Private
 FItems : Array of TMyAvstractClass;
 Function GetItem(Num:Integer):TMyAbstractItem;virtual;abstract;
Public
 Property Items[Num:Integer]:TMyAbstractClass Read GetItem;
End;

TMyObj1 = Class(TMyAbstratctClass)
Private
 Function GetItem(Num:Integer):TMyAbstractItem;override;
End;

Function TMyObj1.GetItem;
Begin
 If Num<Length(FItems) Then  Result := FItems[Num];
End;


Хотя такую функцию можно определить и не астрактно в базовом классе.


 
YuRock ©   (2004-03-09 19:52) [29]

> Defunct ©   (09.03.04 19:40) [28]
> Какая разница что перекрывать? Private секция определяет только область видимости функции.

И все-же я не понимаю, как можно перекрыть метод, которого нет... может, объясните?


 
vuk ©   (2004-03-09 20:02) [30]

to YuRock:
>как можно перекрыть метод, которого нет... может, объясните?
А кто сказал, что его нет?


 
Тимохов ©   (2004-03-09 20:05) [31]

Реально не могу прочухать, что хочет сделать автор :))))))


 
Гаврила   (2004-03-09 20:09) [32]

Не определяйте абстракнтые методы через Pointer - дурной стиль, запутаетесь потом.
Более-менее жесткая типизация для того и сделана, чтобы избежать лишних ошибок.
Лучше заменить TCustomRecord на абстрактный класс.
Тем более что поля класса реально все равно хранятся как record.
А первого предка всех  TCustom{Record}Class определите в этом же модуле
такое мое глубочайшее ИМХО


 
Anatoly Podgoretsky ©   (2004-03-09 20:09) [33]

YuRock ©   (09.03.04 19:52) [29]
Не волнуйся это астракция, метода нет, но перекрыть пожалуйста, компилятор предупрежден об этом волшебным словом abstract


 
Serginio666   (2004-03-09 20:11) [34]

http://www.rsdn.ru/article/Delphi/delphiabs.xml


 
Тимохов ©   (2004-03-09 20:11) [35]


> Гаврила   (09.03.04 20:09) [32]

Про классы автору уже советовали.
Вроде как ему нужно именно рекордами.


> Тем более что поля класса реально все равно хранятся как
> record.

Не совсем - в классе выравнивание нельзя отключить, а record - можно (packed). В случае критического отношения к занимаемой памяти может быть важно. Не зная задачи автора сложно понять важно ли ему оптимизация по занимаемой памяти или нет.


 
Гаврила   (2004-03-09 20:15) [36]

>>в классе выравнивание нельзя отключить
Можно
TMyClass = packed class(TObject)


 
YuRock ©   (2004-03-09 20:16) [37]

> vuk ©   (09.03.04 20:02) [30]

Нет - в смысле в области видимости. При попытке написать override еще компилятор должен ошибку выдать (не считая тех редки случаев, когда базовый класс и наследник описаны в одном модуле).

А если попытаться изменить типы параметров и/или их количество - то уже ничего не поможет...


 
YuRock ©   (2004-03-09 20:25) [38]

> Anatoly Podgoretsky ©   (09.03.04 20:09) [33]

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


 
Тимохов ©   (2004-03-09 20:28) [39]


> Гаврила   (09.03.04 20:15) [36]

Согласен полностью.

Но все равно на 4 байта больше (первые 4 байте ссылка на класс).
Мало ли, может автору нужно 5 млн объектов (а это все-таки лишних 20 мег:)))))


 
vuk ©   (2004-03-09 20:30) [40]

Если говорить об виртуальных методах, то абстрактный метод - это виртуальный метод, не имеющий реализации. То есть имеется определение заголовка метода и место этого метода в VMT. То есть говорить о том, что метода нет малость не совсем верно.

to YuRock:
>Нет - в смысле в области видимости.
Вы же так и написали - не считая тех редки случаев, когда базовый класс и наследник описаны в одном модуле. То есть в некоторых случаях все-таки есть.



Страницы: 1 2 вся ветка

Текущий архив: 2004.03.28;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.05 c
14-1077886579
1g0r
2004-02-27 15:56
2004.03.28
Тяпница, можно уже и расслабиться %)


7-1073350787
zumo
2004-01-06 03:59
2004.03.28
соединение и ..... прокси


1-1078830858
Layner
2004-03-09 14:14
2004.03.28
Мастера, как сгенерить код HTML цвета типа #FFCECE, #FFFFFF


3-1077137878
ser_ega
2004-02-18 23:57
2004.03.28
BDE


1-1078220907
Андрей Пономарев
2004-03-02 12:48
2004.03.28
Утечки памяти