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

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

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

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

Сообщение kazalex » 06.12.2014 02:54:27

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

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

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

Так со счетчиком самые нормальные и есть: можно вовне отдать и извне получить.
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

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

Сообщение dedm0zaj » 06.12.2014 03:50:37

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


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

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


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

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

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

Сообщение sign » 06.12.2014 09:47:48

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

:shock:
Интересно, чего я не понял в вашем примере?
У меня вот, ни разу не проходит такое повторить.
1.jpg
У вас нет необходимых прав для просмотра вложений в этом сообщении.
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

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

Сообщение dedm0zaj » 06.12.2014 11:07:01

если кратко, то паскаль - путь наименьшего сопротивлениы
dedm0zaj
постоялец
 
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

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

Сообщение kazalex » 06.12.2014 11:21:59

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.
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

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

Сообщение stanilar » 06.12.2014 15:27:44

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

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

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

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

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

Сообщение dedm0zaj » 07.12.2014 02:12:04

переделал под то, как представляю это я. и это почему то работает. очень странно. наверно в прошлый раз делал что то не так и работало только при замене интерфейса на асбтрактный класс
Код: Выделить всё
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.
dedm0zaj
постоялец
 
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

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

Сообщение Vapaamies » 07.12.2014 05:02:28

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

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

Сообщение dedm0zaj » 07.12.2014 10:17:17

вспомнил в чём проблема. если поочередно присваивать интерфейсу разные классы, то на 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


что я делаю не так?
dedm0zaj
постоялец
 
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

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

Сообщение kazalex » 07.12.2014 11:40:03

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

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

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

Сообщение dedm0zaj » 07.12.2014 12:24:56

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


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

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


вот так?
Код: Выделить всё
var
  Animal            : TAnimal;
  PredatorBehaviour : IBehaviour;
  ShwarcBehaviour   : IBehaviour;

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

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

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

работает. но это всё походит на костыль. понимаю, что интерфейсы применяют для автоматического убийства объектов, но в данном случае я бы предпочел интерфейсы, как в java, ибо выглядели бы куда логичнее.
dedm0zaj
постоялец
 
Сообщения: 108
Зарегистрирован: 05.10.2012 19:55:20

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

Сообщение kazalex » 07.12.2014 13:13:26

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

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

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

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

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

Сообщение dedm0zaj » 07.12.2014 14:06:40

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

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

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

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

Сообщение kazalex » 07.12.2014 14:13:08

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

Логичнее обойтись классом с виртуальными методами.
kazalex
постоялец
 
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

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

Сообщение dedm0zaj » 07.12.2014 14:35:47

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


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

Пред.След.

Вернуться в Потрепаться

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

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

Рейтинг@Mail.ru