Можно ли у наследнике переопределить тип унаследованного поля?
type TA=object pole:byte; end;
TB=object(TA) pole:integer; end;
Компилятор ругается и Faq'e написанно, что нельзя, но неужели нету нормального способа использовать вот этот модуль Односвязный список с использованием ООП (сообщения №5) без ковыряния в его коде, понимая что надо будет изменить некоторые процедуры.
Цитата
В качестве базового типа для всех структур приведенных ниже используется тип Integer (который при желании можно заменить на любой встроенный тип Паскаля: числовой, логический, символьный или строковый).
Эта фраза дает оптимистические надежды. P.S можно ли давать ссылку на конкретное сообщения в теме?
volvo
31.10.2006 12:32
Цитата
Можно ли у наследнике переопределить тип унаследованного поля?
Нет... ПЕРЕопределить ничего из того, что касается полей нельзя...
Цитата
Эта фраза дает оптимистические надежды.
Реализация эти оптимистические надежды превратит в пессимистические... Не все так просто, за возможность использования любого типа ты должен, что понятно, платить... Чем? Размером объекта... Ищи у меня на сайте рабочую реализацию объектов, работающих с любым типом данных...
klem4
31.10.2006 12:40
как вариант (если не обязательно Паскаль) использовать классы в Delphi или C# ... там такое допускается ...
TA = class(TObject) public i: byte; end;
TB = class(TA) public i: Double; end;
или FPC
{$mode DELPHI}
uses crt;
type
TA = class(TObject) private i: byte; end;
TB = class (TA) private i: Integer; end;
begin end.
volvo
31.10.2006 13:06
М
Как вариант - супермодератору смотреть на название форума, если не затруднит!
Устное предупреждение... Дальнейшее подобное поведение будет рассматриваться, как флуд. Со всеми вытекающими... Для Дельфи/FPC/С# есть отдельный форум. Автор задает вопрос в форуме Задачи...
klem4
31.10.2006 13:42
Виноват, можно попробывать обыграть это дело в таком ключе, хотя это всеже изврат:
uses crt;
type
TA = object
p: Pointer;
constructor Create; function GetP: Byte;
end;
TB = Object(TA)
constructor Create; function GetP: Integer;
end;
constructor TA.Create; var pB : ^Byte; begin GetMem(pB, sizeof(Byte)); p := pB; Byte(p^) := 3; end;
constructor TB.Create; var pI: ^Integer; begin GetMem(pI, sizeof(Integer)); p := pI; Integer(p^) := 5; end;
function TA.GetP: Byte; begin GetP := Byte(p^); end;
function TB.GetP: Integer; begin GetP := Integer(p^); end;
Прошу прощения - промазал, а целился в 32 битные компиляторы (Fpc), зато получил извращенный вариант для обычного паскаля. klem4, спасибо, +1 за "изврат" .
volvo
1.11.2006 13:24
Цитата
Можно ли у наследнике переопределить тип унаследованного поля?
Именно так, если я не ошибаюсь, стоял вопрос? И что? Bokul, ты считаешь, что работа с ОДНИМ и тем же полем, расположенным в родителе через переопределенный метод - это аналог того, что ты спросил? Это во-первых...
Во-вторых: код не учитывает "золотое правило ООП": потомок инициализируется через конструктор предка! Иначе будут проблемы. Если надо, могу привести пример, когда ЭТОТ же код (если в него добавить 10 строк, ничего в существующих строках не меняя) при запуске будет зависать... А если инициализировать TB через TA, то... утечка, простите...
Так что...
klem4
1.11.2006 14:02
Покажи подалуйста, инетресно
ps
constructor TB.Create; var pI: ^Integer; begin inherited Create; // ... end;
Поможет ?
volvo
1.11.2006 17:06
uses crt;
const NotEnoughMemory: boolean = false;
procedure getmem(var p: pointer; size: integer); begin
if NotEnoughMemory then p := nil else system.getmem(p, size);
end;
type
TA = object
p: Pointer;
constructor Create; function GetP: Byte;
end;
TB = Object(TA)
constructor Create; function GetP: Integer; end;
constructor TA.Create; var pB : ^Byte; begin if notEnoughMemory then Fail;
GetMem(pB, sizeof(Byte)); p := pB; Byte(p^) := 3; end;
constructor TB.Create; var pI: ^Integer; begin GetMem(pI, sizeof(Integer)); p := pI; Integer(p^) := 5; end;
function TA.GetP: Byte; begin GetP := Byte(p^); end;
function TB.GetP: Integer; begin GetP := Integer(p^); end;
var
a: TA; b: TB; begin a.Create; // big memory request NotEnoughMemory := true;
b.Create; writeln(a.GetP); writeln(b.GetP);
readln; end.
Объясняю ситуацию: инициализировали объект A, потом был запущен какой-то цикл, просящий память у система... Система отдает в этом цикле всю кучу... Я не стал делать сам этот цикл, я смоделировал ситуацию, введя флаг NotEnoughMemory, показывающий наличие/отсутствие свободной памяти... Как только память закончилась, флаг переброшен в True... Теперь вспоминаем, как работает GetMem: если HeapFunc возвращает 1, то при недостатке памяти указатель - нулевой, если 2, то при недостатке памяти система повторяет запрос на распределение памяти ... Ты в своей программе не знаешь, что возвращает HeapFunc, ибо ее подмена может быть сделана в любом подключаемом в Uses модуле... Допустим, возвращает 1 - тогда системный GetMem работает аналогично моему - возвращает Nil... Результат - RunTime Error... Если HeapFunc будет возвращать 2, получишь бесконечную очередь запросов на выделение памяти и отказов, опять запрос - отказ...
Цитата
Поможет ?
Поможет, только не в том, что ошибки не будет, а в том, что ошибка будет централизованно (в самом первом объекте цепочки наследования) обрабатываться, и экземпляр объекта B просто не будет создан...
Bokul
2.11.2006 11:10
Цитата
Именно так, если я не ошибаюсь, стоял вопрос? И что? Bokul, ты считаешь, что работа с ОДНИМ и тем же полем, расположенным в родителе через переопределенный метод - это аналог того, что ты спросил? Это во-первых...
Да ты прав, но все же на том этапе изучения работы с объектами, на котором нахожусь я, интересно по больше узнать о технике работы с ними, о всях таких "извратах". А за золотое правило и пример спасибо, +1.
klem4
2.11.2006 12:18
Может я конечно что-то не понял, но всеже, Volvo, ты согласишься с тем что ошибка в моей программе связана не с какими-то аглоритмическими/логическими огрехами, а с если так можно сказать издержками программирования. Программе для работы нужна динамическая пямять, если ее нет, будет ошибка. Это логично.
volvo
2.11.2006 14:44
Цитата
Программе для работы нужна динамическая пямять, если ее нет, будет ошибка. Это логично.
ЭТО - Логично...
А вот КАК узнать, что динамической памяти нет, и не завершить программу с RunTime Error, а выдать простое и понятное сообщение, и при этом, возможно, еще откатиться назад, чтобы удалить ранее созданные объекты (если, например, они создавались для поддержки работоспособности того, который не смог инициализироваться), чтобы корректно сохранить информацию из них куда-нибудь в файл, а не потерять ее (кто знает, сколько времени программа накапливала информацию, может она работала несколько часов, и что? Все будет утеряно?)... Это чья задача? Операционной системы/компилятора, или все-же твоя, как программиста?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.