Параметризовать конструктор

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Re: Параметризовать конструктор

Сообщение MylnikovDm » 04.08.2014 17:52:55

Vapaamies писал(а):Не используем запрещенные приемы, не передергиваем! Я ясно написал про SaveToFile, а не LoadFromFile, хоть их код различается несильно. Ваши архитекторы что, так сильно не уважают свой труд, что не сохраняют файлы и отключают автоматическое сохранение, если оно есть?


SaveToFile записывает данные из существующих объектов в памяти на диск, то есть, она не должна создавать новые объекты в памяти. Можете привести пример когда SaveToFile, которая в процессе работы создаёт новые объекты и выделяет под них память? Так что никакого передёргивания.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение Vapaamies » 04.08.2014 20:42:00

MylnikovDm писал(а):Можете привести пример когда SaveToFile, которая в процессе работы создаёт новые объекты и выделяет под них память?

SaveToFile создает экземпляр TFileStream, передает его в SaveToStream, а после возврата уничтожает.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 291
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Параметризовать конструктор

Сообщение MylnikovDm » 04.08.2014 21:02:06

Vapaamies писал(а):SaveToFile создает экземпляр TFileStream, передает его в SaveToStream, а после возврата уничтожает.

???!!! Вы это серьёзно, или вы так пошутили?!
При загрузке сложной структуры данных вызываются тысячи, если не десятки тысяч конструкторов и GetMem для выделения памяти под загружаемые объекты!
А вы мне тут с одним созданием TFileStream мозги парите, да ещё и говорите про запрещённые приёмы и передёргивания? :D :D :D :D
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение Vapaamies » 04.08.2014 23:40:31

MylnikovDm писал(а):А вы мне тут с одним созданием TFileStream мозги парите, да ещё и говорите про запрещённые приёмы и передёргивания? :D :D :D :D

Парю. Жарко же. За компанию. :lol: Всё равно умные примеры в голову не приходят. :mrgreen:
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 291
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Параметризовать конструктор

Сообщение stanilar » 13.08.2014 08:32:48

Как давно я не был тут...

Вопрос на засыпку для Дож, вот такой вариант кода Вас устроит:
(или я совсем забыл как работает компилятор, ибо после 3 месяцев отдыха неохота запускать...)

Код: Выделить всё

type
TAnimal = object
  FName: AnsiString;
  constructor Init(const Name: AnsiString);
  procedure TellAboutYourSelf; virtual; abstract;
end;

TCat = object(TAnimal)
  procedure TellAboutYourSelf; virtual;
end;

TDog = object(TAnimal)
  procedure TellAboutYourSelf; virtual;
end;

constructor TAnimal.Init(const Name: AnsiString);
begin
  FName := Name;
end;


procedure TCat.TellAboutYourSelf;
begin
  Writeln('Я кот по имени ', FName, '.');
end;

procedure TDog.TellAboutYourSelf;
begin
  Writeln('Я ', FName, ', гав-гав!');
end;

var
  Pet: TAnimal;

begin
  Pet.Init('Бусик');

  Pet := TCat(Pet)
  Pet.TellAboutYourSelf;
  Pet := TDog (Pet)
  Pet.TellAboutYourSelf;
end.
stanilar
постоялец
 
Сообщения: 289
Зарегистрирован: 09.03.2010 19:09:02

Re: Параметризовать конструктор

Сообщение zub » 13.08.2014 12:57:01

>>(или я совсем забыл как работает компилятор, ибо после 3 месяцев отдыха неохота запускать...)
Видимо да, это не будет работать
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Параметризовать конструктор

Сообщение Дож » 14.08.2014 01:48:32

stanilar писал(а):Вопрос на засыпку для Дож, вот такой вариант кода Вас устроит:
(или я совсем забыл как работает компилятор, ибо после 3 месяцев отдыха неохота запускать...)

Код: Выделить всё

type
TAnimal = object
  FName: AnsiString;
  constructor Init(const Name: AnsiString);
  procedure TellAboutYourSelf; virtual; abstract;
end;

TCat = object(TAnimal)
  procedure TellAboutYourSelf; virtual;
end;

TDog = object(TAnimal)
  procedure TellAboutYourSelf; virtual;
end;

constructor TAnimal.Init(const Name: AnsiString);
begin
  FName := Name;
end;


procedure TCat.TellAboutYourSelf;
begin
  Writeln('Я кот по имени ', FName, '.');
end;

procedure TDog.TellAboutYourSelf;
begin
  Writeln('Я ', FName, ', гав-гав!');
end;

var
  Pet: TAnimal;

begin
  Pet.Init('Бусик');

  Pet := TCat(Pet)
  Pet.TellAboutYourSelf;
  Pet := TDog (Pet)
  Pet.TellAboutYourSelf;
end.

Интересный ход! Но, к сожалению, данный код не заработает: приведение к типу в данном случае ничего не сделает с данными (и, в частности, с VMT), по сути Pet запишется в себя.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение MylnikovDm » 14.08.2014 12:39:11

Дож писал(а):Но, к сожалению, данный код не заработает: приведение к типу в данном случае ничего не сделает с данными (и, в частности, с VMT), по сути Pet запишется в себя.

Мало того, он так и останется типа TAnimal, а значит будет ошибка при попытке вызвать абстрактный метод TellAboutYourSelf из класса TAnimal.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение Vapaamies » 15.08.2014 15:44:30

Так-с, жара спа́ла, нужно просыпаться и соображать. Помню, что обещал набросать образцы кода и посмотреть ассемблерный подстрочник. Если тема по-прежнему интересна, так и сделаю.

Жалко, в последнее время в метро приходится мало ездить. Размышления на тему ARC, escape analysis и растягиваемых объектов -- тема как раз для метро.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 291
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Параметризовать конструктор

Сообщение zub » 15.08.2014 16:32:01

>>Так-с, жара спа́ла
Похоже пока нет)) Зачем могут пригодиться "расширяемые" объекты? мало того они уже есть в виде виртуальных методов и пропертей. ООП на то и придуман чтоб унифицировать доступ к разнородным объектам, не задумываясь где по факту лежат конкретные данные.
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Параметризовать конструктор

Сообщение stanilar » 15.08.2014 17:57:14

До меня немного дошло что и зачем было сделано. Не могу удержаться от комментария в виде кода:

Код: Выделить всё
type

{ TAnimal }

type

TTellAboutClass = class of TTellAbout;

TAnimal = object
  FName: AnsiString;
  TellAbout : TTellAboutClass;

  constructor Init(const Name: AnsiString);
  procedure TellAboutYourSelf;
end;

TTellAbout = class
public
  class procedure TellAboutYourSelf(Anim : TAnimal); virtual; abstract;
end;

TCat = class(TTellAbout)
  class procedure TellAboutYourSelf(Anim : TAnimal); override;
end;

TDog = class(TTellAbout)
  class procedure TellAboutYourSelf(Anim : TAnimal); override;
end;


procedure TAnimal.TellAboutYourSelf;
begin
  TellAbout.TellAboutYourSelf(Self);
end;   

class procedure TCat.TellAboutYourSelf(Anim : TAnimal);
begin
    Showmessage('Я '+Anim.FName+' кот');
end;

class procedure TDog.TellAboutYourSelf(Anim : TAnimal);
begin
  Showmessage('Я '+Anim.FName+' гав-гав!');
end;   

var
  Pet: TAnimal;
begin
  Pet.Init('Бусик');
  Pet.TellAbout := TCat;
  Pet.TellAboutYourSelf;

  Pet.TellAbout := TDog;
  Pet.TellAboutYourSelf;
end; 



Кода конечно больше, но он (отделяет мух от котлет) прозрачней для понимания.

P.S. Как сделать текст зачеркнутым?
stanilar
постоялец
 
Сообщения: 289
Зарегистрирован: 09.03.2010 19:09:02

Re: Параметризовать конструктор

Сообщение Дож » 15.08.2014 18:56:53

Или даже так, «Pure Pascal» версия :)
Код: Выделить всё
type
  PPetBehaviour = ^TPetBehaviour;

  TPet = object
    Name: AnsiString;
    Behaviour: PPetBehaviour;
    constructor Init(const _Name: AnsiString);
    procedure TellAboutYourSelf; inline;
  end;

  TPetBehaviour = record
    TellAboutYourSelf: procedure (const Pet: TPet);
  end;

constructor TPet.Init(const _Name: AnsiString);
begin
  Name := _Name;
end;

procedure TPet.TellAboutYourSelf;
begin
  Behaviour^.TellAboutYourSelf(Self);
end;

procedure TCat_TellAbout(const Pet: TPet); // TCat implementation part
begin
  Writeln('Я кот по имени ', Pet.Name, '.');
end;

procedure TDog_TellAbout(const Pet: TPet); // TDog implementation part
begin
  Writeln('Я ', Pet.Name, ', гав-гав!');
end;

const
  TCat: TPetBehaviour = ( // declaration of TCat
    TellAboutYourSelf: @TCat_TellAbout
  );
  TDog: TPetBehaviour = ( // declaration of TDog
    TellAboutYourSelf: @TDog_TellAbout
  );

// using
var
  Pet: TPet;

begin
  Pet.Init('Бусик');

  Pet.Behaviour := @TCat;
  Pet.TellAboutYourSelf;
  Pet.Behaviour := @TDog;
  Pet.TellAboutYourSelf;
end.


Что лично мне не нравится в подобных подходах:
1. Каждый «виртуальный» метод нужно реализовывать через явный параметр объекта (Animal), поля и методы не видны сами по себе.
2. Не вполне понятно как правильно объявить protected-поля в TAnimal, чтобы только потомки TTellAbout их видели.

object не привносит сам по себе что-то новое функционально (всё можно реализовать самостоятельно через ссылки на функции), но даёт некий синтаксический сахар и хотелось бы сохранить по-максимуму наглядность реализации конкретный классов.

Это я выступаю в защиту параметризации конструктора, а не смены поведения на лету (что действительно лучше реализовывать самостоятельно, а не хакать vmt).
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение stanilar » 15.08.2014 19:43:30

Дож писал(а):а не хакать vmt


Не сочтите за занудство: если бы Вы хакнули vmt, вы бы сменили поведение всего типа. Потому как vmt принадлежит типу, а не созданной из типа сущности. Лучше сказать бала хакнута запись объекта, в результате чего вызов методов объекта стал соответствовать ожидаемому. Но меня не покидает ощущение что это соотвествие случайно.

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

Добавлено спустя 8 минут 41 секунду:
Кстати, в «Pure Pascal» версии похоже теряется проверка типов компилятором.
Так понимаю, что вот это будет скомпилировано без ошибок:
Код: Выделить всё
  Pet.Behaviour := @Pet;
stanilar
постоялец
 
Сообщения: 289
Зарегистрирован: 09.03.2010 19:09:02

Re: Параметризовать конструктор

Сообщение Дож » 15.08.2014 19:57:20

Если планируется разносить потомков по разным юнитам,

Да, планируется.
то это повод собирать специфичный и связанный код разных наследников в одном юните

Вот это твист! «Если планируется разносить потомков по разным юнитам, то это повод собрать разных наследников в одном юните». Что Вы имели в виду? :)

Добавлено спустя 7 минут 38 секунд:
stanilar писал(а):Добавлено спустя 8 минут 41 секунду:
Кстати, в «Pure Pascal» версии похоже теряется проверка типов компилятором.
Так понимаю, что вот это будет скомпилировано без ошибок:
Код: Выделить всё
  Pet.Behaviour := @Pet;


Да, компилируется без ошибок и это является для меня некоторой неожиданностью. Почему так происходит? Вроде же и в левой части, и правой — типизированные указатели.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение stanilar » 15.08.2014 20:21:18

Дож писал(а):Что Вы имели в виду? :)


stanilar писал(а):повод собирать специфичный и связанный код разных наследников в одном юните


Добавлено спустя 5 минут 53 секунды:
Дож писал(а):Почему так происходит?

Ну справа взятие адреса вообще-то. И я вообще-то против того, если в этом месте компилятор заругается и перестанет работать. Ибо много грязных хаков раскидано по разным проектам...

Добавлено спустя 3 минуты 41 секунду:
stanilar писал(а):повод собирать специфичный и связанный код разных наследников в одних и тех же юнитах
stanilar
постоялец
 
Сообщения: 289
Зарегистрирован: 09.03.2010 19:09:02

Пред.След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23

Рейтинг@Mail.ru