Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Наследование полей

Автор: Bokul 31.10.2006 10:52

Можно ли у наследнике переопределить тип унаследованного поля?

type
TA=object
pole:byte;
end;

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

Компилятор ругается и Faq'e написанно, что нельзя, но неужели нету нормального способа использовать вот этот модуль http://forum.pascal.net.ru/index.php?showtopic=2085 без ковыряния в его коде, понимая что надо будет изменить некоторые процедуры.
Цитата
В качестве базового типа для всех структур приведенных ниже используется тип 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 smile.gif

{$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

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

Устное предупреждение... Дальнейшее подобное поведение будет рассматриваться, как флуд. Со всеми вытекающими... Для Дельфи/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;

var

a: TA;
b: TB;
begin
a.Create;
b.Create;
writeln(a.GetP);
writeln(b.GetP);
readln;
end.

Автор: Bokul 1.11.2006 9:35

Цитата
Автор задает вопрос в форуме Задачи...

Прошу прощения - промазал, а целился в 32 битные компиляторы (Fpc), зато получил извращенный вариант для обычного паскаля. klem4, спасибо, +1 за "изврат" good.gif .

Автор: volvo 1.11.2006 13:24

Цитата
Можно ли у наследнике переопределить тип унаследованного поля?
Именно так, если я не ошибаюсь, стоял вопрос? И что? Bokul, ты считаешь, что работа с ОДНИМ и тем же полем, расположенным в родителе через переопределенный метод - это аналог того, что ты спросил? blink.gif Это во-первых...

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

Так что...

Автор: klem4 1.11.2006 14:02

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

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, а выдать простое и понятное сообщение, и при этом, возможно, еще откатиться назад, чтобы удалить ранее созданные объекты (если, например, они создавались для поддержки работоспособности того, который не смог инициализироваться), чтобы корректно сохранить информацию из них куда-нибудь в файл, а не потерять ее (кто знает, сколько времени программа накапливала информацию, может она работала несколько часов, и что? Все будет утеряно?)... Это чья задача? Операционной системы/компилятора, или все-же твоя, как программиста?