Помощь - Поиск - Пользователи - Календарь
Полная версия: Наследование полей
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Bokul
Можно ли у наследнике переопределить тип унаследованного поля?
type
TA=object
pole:byte;
end;

TB=object(TA)
pole:integer;
end;

Компилятор ругается и Faq'e написанно, что нельзя, но неужели нету нормального способа использовать вот этот модуль Односвязный список с использованием ООП (сообщения №5) без ковыряния в его коде, понимая что надо будет изменить некоторые процедуры.
Цитата
В качестве базового типа для всех структур приведенных ниже используется тип Integer (который при желании можно заменить на любой встроенный тип Паскаля: числовой, логический, символьный или строковый).

Эта фраза дает оптимистические надежды.
P.S можно ли давать ссылку на конкретное сообщения в теме?
volvo
Цитата
Можно ли у наследнике переопределить тип унаследованного поля?
Нет... ПЕРЕопределить ничего из того, что касается полей нельзя...

Цитата
Эта фраза дает оптимистические надежды.
Реализация эти оптимистические надежды превратит в пессимистические... Не все так просто, за возможность использования любого типа ты должен, что понятно, платить... Чем? Размером объекта... Ищи у меня на сайте рабочую реализацию объектов, работающих с любым типом данных...
klem4
как вариант (если не обязательно Паскаль) использовать классы в Delphi или C# ... там такое допускается ...


TA = class(TObject)
public i: byte;
end;

TB = class(TA)
public i: Double;
end;


или FPC smile.gif

{$mode DELPHI}

uses crt;

type

TA = class(TObject)
private
i: byte;
end;

TB = class (TA)
private
i: Integer;
end;

begin
end.
volvo
М
Как вариант - супермодератору смотреть на название форума, если не затруднит! dry.gif

Устное предупреждение... Дальнейшее подобное поведение будет рассматриваться, как флуд. Со всеми вытекающими... Для Дельфи/FPC/С# есть отдельный форум. Автор задает вопрос в форуме Задачи...

klem4
Виноват, можно попробывать обыграть это дело в таком ключе, хотя это всеже изврат:

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;

var

a: TA;
b: TB;
begin
a.Create;
b.Create;
writeln(a.GetP);
writeln(b.GetP);
readln;
end.
Bokul
Цитата
Автор задает вопрос в форуме Задачи...

Прошу прощения - промазал, а целился в 32 битные компиляторы (Fpc), зато получил извращенный вариант для обычного паскаля. klem4, спасибо, +1 за "изврат" good.gif .
volvo
Цитата
Можно ли у наследнике переопределить тип унаследованного поля?
Именно так, если я не ошибаюсь, стоял вопрос? И что? Bokul, ты считаешь, что работа с ОДНИМ и тем же полем, расположенным в родителе через переопределенный метод - это аналог того, что ты спросил? blink.gif Это во-первых...

Во-вторых: код не учитывает "золотое правило ООП": потомок инициализируется через конструктор предка! Иначе будут проблемы. Если надо, могу привести пример, когда ЭТОТ же код (если в него добавить 10 строк, ничего в существующих строках не меняя) при запуске будет зависать... А если инициализировать TB через TA, то... утечка, простите...

Так что...
klem4
Покажи подалуйста, инетресно smile.gif

ps

constructor TB.Create;
var
pI: ^Integer;
begin
inherited Create;
// ...
end;


Поможет ?
volvo
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
Цитата
Именно так, если я не ошибаюсь, стоял вопрос? И что? Bokul, ты считаешь, что работа с ОДНИМ и тем же полем, расположенным в родителе через переопределенный метод - это аналог того, что ты спросил? Это во-первых...

Да ты прав, но все же на том этапе изучения работы с объектами, на котором нахожусь я, интересно по больше узнать о технике работы с ними, о всях таких "извратах". А за золотое правило и пример спасибо, +1.
klem4
Может я конечно что-то не понял, но всеже, Volvo, ты согласишься с тем что ошибка в моей программе связана не с какими-то аглоритмическими/логическими огрехами, а с если так можно сказать издержками программирования. Программе для работы нужна динамическая пямять, если ее нет, будет ошибка. Это логично.
volvo
Цитата
Программе для работы нужна динамическая пямять, если ее нет, будет ошибка. Это логично.
ЭТО - Логично...

А вот КАК узнать, что динамической памяти нет, и не завершить программу с RunTime Error, а выдать простое и понятное сообщение, и при этом, возможно, еще откатиться назад, чтобы удалить ранее созданные объекты (если, например, они создавались для поддержки работоспособности того, который не смог инициализироваться), чтобы корректно сохранить информацию из них куда-нибудь в файл, а не потерять ее (кто знает, сколько времени программа накапливала информацию, может она работала несколько часов, и что? Все будет утеряно?)... Это чья задача? Операционной системы/компилятора, или все-же твоя, как программиста?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.