Извечный холивар ))

Любые обсуждения, не нарушающие правил форума.

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

kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Извечный холивар ))

Сообщение kazalex »

dedm0zaj писал(а):переменные класса это не указатели, а ссылки.

Указатели-указатели. Ссылками они стали только в мобильных компиляторах дельфей с поддержкой ARC т.к. стала обеспечиваться очистка слабых (weak) ссылок. Правда сделано это через такую #опу, что в многопоточке может очень сильно просадить производительность.

dedm0zaj писал(а):ну и ещё хотелось бы нормальных интерфейсов, а не со счетчиком ссылок.

Так со счетчиком самые нормальные и есть: можно вовне отдать и извне получить.
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

kazalex писал(а):Ссылками они стали только в мобильных компиляторах дельфей с поддержкой ARC


как по мне, это лишь дополнительные возможности для работы со ссылками.
а объект-ссылку определяет ненужность разыменовывания при обращении.

kazalex писал(а):Так со счетчиком самые нормальные и есть: можно вовне отдать и извне получить.


у меня допустим есть класс "животное". и есть интерфейс у этого класса "поведение". ("животное" не реализует этот интерфейс, а этот интерфейс просто входит в класс).
и есть много других классов ("хищник", "травоядное", etc), которые реализуют интерфейс "поведение".

я создаю объект "животного" и присваиваю интерфейсу "поведение" один из классов (например "хищник"). в OP я такое сделать не могу, поскольку там, где интерфейс создаётся, тут же, по выходу из функции, уничтожается. приходится юзать абстрактные классы с абстрактными методами.
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Re: Извечный холивар ))

Сообщение sign »

VirtUX писал(а):myfunc := myfunc(); // Обращение к результату функции без параметров
a := myfunc; // обращение к переменно myfunc

:shock:
Интересно, чего я не понял в вашем примере?
У меня вот, ни разу не проходит такое повторить.
1.jpg
У вас нет необходимых прав для просмотра вложений в этом сообщении.
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

если кратко, то паскаль - путь наименьшего сопротивлениы
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Извечный холивар ))

Сообщение kazalex »

dedm0zaj писал(а):а объект-ссылку определяет ненужность разыменовывания при обращении.

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

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

Интерфейс не умрет до дех пор пока не выйдет из зоны видимости последняя ссылка на него. Если же интерфейс чему-то присвоили, с чего он должен умереть по выходу из функции? Я так понимаю описана классическая ситуация агрегирования интерфейса:

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

Type

 //
 IBehaviour = Interface

  Procedure DoIt;

 End;
 //

 //
 TAnimal = Class(TObject, IBehaviour)

  Strict Private

   FBehaviour : IBehaviour;

   Property Behaviour : IBehaviour Read FBehaviour Implements IBehaviour;

  Public

   Constructor Create(Const ABehaviour : IBehaviour);

 End;
 //

 //
 TPredatorBehaviour = Class(TInterfacedObject, IBehaviour)

  Procedure OmnomNom;

  Procedure IBehaviour.DoIt = OmNomNom;

 End;
 //

{ TAnimal }

//
Constructor TAnimal.Create(Const ABehaviour : IBehaviour);
Begin

 Inherited Create;

 FBehaviour := ABehaviour;

End;
//

{ TPredatorBehaviour }

//
Procedure TPredatorBehaviour.OmNomNom;
Begin

 WriteLn('Om-nom-nom');

End;
//

...

 Animal : TAnimal;

Begin

 Animal := TAnimal.Create(TPredatorBehaviour.Create);

 IBehaviour(Animal).DoIt;

 Animal.Free;

End.
stanilar
постоялец
Сообщения: 289
Зарегистрирован: 09.03.2010 18:09:02

Re: Извечный холивар ))

Сообщение stanilar »

dedm0zaj писал(а):я создаю объект "животного" и присваиваю интерфейсу "поведение" один из классов (например "хищник"). в OP я такое сделать не могу, поскольку там, где интерфейс создаётся, тут же, по выходу из функции, уничтожается. приходится юзать абстрактные классы с абстрактными методами.

Т.е. Вы хотите, чтоб интерфейсы ссылались не только на объекты, но и на классы?

Добавлено спустя 12 минут 10 секунд:
SSerge писал(а):переменные типа class на самом деле являются указателем, а к переменной-указателю исходным синтаксисом положен символ "^"

Переменные типа class являются типизированным указателем, а не просто указателем. Работу с типами поддерживают любые языки. Символ "^" как раз не нужен, хотя он бы более соответствовал реальному положению вещей, хотя бы для избежания странных вопросов " ...почему при вызове TObject.Free, переменная не становится равной nil ?".
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

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

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

program project1;

{$mode objfpc}{$H+}

Type
  IBehaviour = Interface
    Procedure DoIt;
  End;

  TAnimal = Class
    Strict Private
      FBehaviour : IBehaviour;
    Public
      procedure SetBehav(behav : IBehaviour);
      procedure DoIt;
  End;

  TPredatorBehaviour = Class(TInterfacedObject, IBehaviour)
    public
      Procedure DoIt;
  End;

  TShwarcBehaviour = Class(TInterfacedObject, IBehaviour)
    public
      Procedure DoIt;
  End;

//============================================================

procedure TAnimal.SetBehav(behav : IBehaviour);
Begin
  FBehaviour := behav;
End;

procedure TAnimal.DoIt;
Begin
  FBehaviour.DoIt;
End;

procedure TPredatorBehaviour.DoIt;
begin
  WriteLn('Om-nom-nom');
end;

procedure TShwarcBehaviour.DoIt;
begin
  WriteLn('ShwarcNeger-Tysh-Tydysh');
end;

//============================================================

var
  Animal            : TAnimal;
  PredatorBehaviour : TPredatorBehaviour;
  ShwarcBehaviour   : TShwarcBehaviour;

Begin
  Animal            := TAnimal.Create;
  PredatorBehaviour := TPredatorBehaviour.Create;
  ShwarcBehaviour   := TShwarcBehaviour.Create;
  Animal.SetBehav(PredatorBehaviour);

  Animal.DoIt;

  Animal.SetBehav(ShwarcBehaviour);

  Animal.DoIt;

  Animal.Free;
  PredatorBehaviour.Free;
  ShwarcBehaviour.Free;
End.
Аватара пользователя
Vapaamies
постоялец
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург
Контактная информация:

Re: Извечный холивар ))

Сообщение Vapaamies »

Вот паскалисты ведь, -- и посраться нормально не могут. На каком другом форуме может так случиться, что холивар кому-то помог? :mrgreen:
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

вспомнил в чём проблема. если поочередно присваивать интерфейсу разные классы, то на 5-ом присваивании выбрасывается исключение

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

... {начало см. выше}

Begin
  Animal            := TAnimal.Create;
  PredatorBehaviour := TPredatorBehaviour.Create;
  ShwarcBehaviour   := TShwarcBehaviour.Create;

  Animal.SetBehav(PredatorBehaviour);
  Animal.SetBehav(ShwarcBehaviour);
  Animal.SetBehav(PredatorBehaviour);
  Animal.SetBehav(ShwarcBehaviour);
  Animal.SetBehav(PredatorBehaviour);
  Animal.SetBehav(ShwarcBehaviour);
  Animal.SetBehav(PredatorBehaviour);
  Animal.SetBehav(ShwarcBehaviour);
  Animal.SetBehav(PredatorBehaviour);
  Animal.SetBehav(ShwarcBehaviour);

  Animal.DoIt;

  Animal.Free;
  PredatorBehaviour.Free;
  ShwarcBehaviour.Free;
End.


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

An unhandled exception occurred at $08081914 :
EAccessViolation : Access violation
  $08081914
  $0805657C
  $080480E4
  $08048267


===========================================

заменяем интерфейс на абстрактный класс и всё чики пуки

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

program project1;

{$mode objfpc}{$H+}

//Type
//  IBehaviour = Interface
//    Procedure DoIt;
//  End;

  Type
    IBehaviour = class
      Procedure DoIt; virtual; abstract;
    End;

  TAnimal = Class
    Strict Private
      FBehaviour : IBehaviour;
    Public
      procedure SetBehav(behav : IBehaviour);
      procedure DoIt;
  End;

  TPredatorBehaviour = Class({TInterfacedObject,} IBehaviour)
    public
      Procedure DoIt; override;
  End;

  TShwarcBehaviour = Class({TInterfacedObject,} IBehaviour)
    public
      Procedure DoIt; override;
  End;

//============================================================

procedure TAnimal.SetBehav(behav : IBehaviour);
Begin
  FBehaviour := behav;
End;

procedure TAnimal.DoIt;
Begin
  FBehaviour.DoIt;
End;

procedure TPredatorBehaviour.DoIt;
begin
  WriteLn('Om-nom-nom');
end;

procedure TShwarcBehaviour.DoIt;
begin
  WriteLn('ShwarcNeger-Tysh-Tydysh');
end;

//============================================================

var
  Animal            : TAnimal;
  PredatorBehaviour : TPredatorBehaviour;
  ShwarcBehaviour   : TShwarcBehaviour;

Begin
  Animal            := TAnimal.Create;
  PredatorBehaviour := TPredatorBehaviour.Create;
  ShwarcBehaviour   := TShwarcBehaviour.Create;

  Animal.SetBehav(PredatorBehaviour);  Animal.DoIt;
  Animal.SetBehav(ShwarcBehaviour);    Animal.DoIt;
  Animal.SetBehav(PredatorBehaviour);  Animal.DoIt;
  Animal.SetBehav(ShwarcBehaviour);    Animal.DoIt;
  Animal.SetBehav(PredatorBehaviour);  Animal.DoIt;
  Animal.SetBehav(ShwarcBehaviour);    Animal.DoIt;
  Animal.SetBehav(PredatorBehaviour);  Animal.DoIt;
  Animal.SetBehav(ShwarcBehaviour);    Animal.DoIt;
  Animal.SetBehav(PredatorBehaviour);  Animal.DoIt;
  Animal.SetBehav(ShwarcBehaviour);    Animal.DoIt;

  Animal.Free;
  PredatorBehaviour.Free;
  ShwarcBehaviour.Free;
End.

вывод:

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

Om-nom-nom
ShwarcNeger-Tysh-Tydysh
Om-nom-nom
ShwarcNeger-Tysh-Tydysh
Om-nom-nom
ShwarcNeger-Tysh-Tydysh
Om-nom-nom
ShwarcNeger-Tysh-Tydysh
Om-nom-nom
ShwarcNeger-Tysh-Tydysh


что я делаю не так?
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Извечный холивар ))

Сообщение kazalex »

dedm0zaj писал(а): если поочередно присваивать интерфейсу разные классы, то на 5-ом присваивании выбрасывается исключение

Что не удивительно т.к. после второго присваивания, объект реализующий интерфейс хищника умирает. Замени объектные типы (переменные поведения) на интерфейсные и будет тебе счастье. Или, если уж совсем никак не хочется расставаться с классами, в базовом классе поведения реализуй собственный IUnknown (см. TComponent, например).
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

kazalex писал(а):после второго присваивания, объект реализующий интерфейс хищника умирает


да, да. это имел в виду. правда не понятно, почему не выкидывает при повторном присвоении, а позже.

kazalex писал(а):Замени объектные типы (переменные поведения) на интерфейсные


вот так?

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

var
  Animal            : TAnimal;
  PredatorBehaviour : IBehaviour;
  ShwarcBehaviour   : IBehaviour;

Begin
  Animal            := TAnimal.Create;
  PredatorBehaviour := TPredatorBehaviour.Create;
  ShwarcBehaviour   := TShwarcBehaviour.Create;

щас попробую.

========================

работает. но это всё походит на костыль. понимаю, что интерфейсы применяют для автоматического убийства объектов, но в данном случае я бы предпочел интерфейсы, как в java, ибо выглядели бы куда логичнее.
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Извечный холивар ))

Сообщение kazalex »

dedm0zaj писал(а):правда не понятно, почему не выкидывает при повторном присвоении, а позже.

На освобожденном месте не сразу появляется мусор, поэтому некоторое время может работать даже некорректный код.

dedm0zaj писал(а):понимаю, что интерфейсы применяют для автоматического убийства объектов, но в данном случае я бы предпочел интерфейсы, как в java, ибо выглядели бы куда логичнее

Не, интерфейсы применяются по назначению, а именно для выделения общей функциональности у классов без единого предка (в твоем случае они, как-бы, вообще не нужны). Автоматическое управление временем жизни это просто приятное дополнение и следствие их совместимости с COM.
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

kazalex писал(а):в твоем случае они, как-бы, вообще не нужны

а как нужно? :?

в моём случае понимаю интерфейс, как порт для присоединения дополнительного функционала.
если в метафоре, но могу описать так:
у нас есть денди, у которого есть порт для картриджей. денди это объект, порт это интерфейс в объекте. получается, что денди может выполнять функционал всех картриджей (картриджи - тоже объекты), которые реализуют интерфейс в денди.
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Re: Извечный холивар ))

Сообщение kazalex »

dedm0zaj писал(а):а как нужно?

Логичнее обойтись классом с виртуальными методами.
dedm0zaj
постоялец
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

Re: Извечный холивар ))

Сообщение dedm0zaj »

kazalex писал(а):Логичнее обойтись классом с виртуальными методами


т.е. как я и предлагал заменить интерфейс абстрактным классом. да, для OP так логичнее.
Ответить