Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Generics, Interfaces и реализация / 15 сообщений из 15, страница 1 из 1
19.07.2017, 12:18:29
    #39491475
SolidSnake
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
Добрый день!

Строится структура приложения от интерфейсов.
Есть сложность при работе с дженериками, не понятно как инстанцировать реализацию и запихнуть её в поле.
Сделал пример:

Интерфейс:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
unit Int;

interface

uses
  System.SysUtils,
  System.Contnrs,
  System.Generics.Collections,
  System.Classes;

type

  // Интерфейсы для реализации дополнительных классов
  IFunctionalInterface = interface
    ['{72DE63BB-DA79-4FAC-8FEC-F12671B4DC52}']
    {
      Тут методы, поля.
    }
  end;

  IAnotherInterface = interface
    ['{DF9A0110-D588-45B6-8F8C-BE4F3CBE3555}']
    {
      Тут методы, поля.
    }
  end;

  // Интерфейс для главного класса
  IMainInterface = interface
    ['{D29A0190-F894-493F-BA97-564C81D49499}']
    function GetFunctional(): IFunctionalInterface;
    function GetCompGeneric(): TList<IAnotherInterface>;
    property Funtional: IFunctionalInterface read GetFunctional;
    // Здесь описывается типовой класс TList c элементами, мы не имеем представления какая будет реализация у элементов,
    // но она должна реализовывать всё, что описано в IAnotherInterface
    property CompGeneric: TList<IAnotherInterface> read GetCompGeneric;
  end;

implementation

end.


Реализация:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
unit Cls;

interface

uses
  {RTL}
  System.SysUtils,
  System.Contnrs,
  System.Generics.Collections,
  System.Classes,
  int;

type

  // Класс реализующий главный интерфейс IMainInterface
  // Этот класс - единственное, что видно снаружи модуля
  TMainClass = class(TInterfacedPersistent, IMainInterface)
  private
    FFunctional: IFunctionalInterface;
    // Поскольку реализуется интерфейс, TList идет с IAnotherInterface
    FAnotherInterface: TList<IAnotherInterface>;
    function GetFunctional(): IFunctionalInterface;
    function GetCompGeneric(): TList<IAnotherInterface>;
  public
    constructor Create();
    destructor Destroy(); override;
  end;

implementation

type

  // Реализации других интерфейсов
  TFunctionalInterface = class(TInterfacedPersistent, IFunctionalInterface)
    {
      Тут методы, поля.
    }
  end;

  TIAnotherInterface = class(TInterfacedPersistent, IAnotherInterface)
    {
      Тут методы, поля.
    }
  end;

  { MainClass }

constructor TMainClass.Create();
begin
  // Помещаем в интерфейсное поле FFunctional реализацию TFunctionalInterface
  FFunctional := TFunctionalInterface.Create();
  // Теперь надо как-то поместить реализацию в FAnotherInterface
  FAnotherInterface := TList<TIAnotherInterface>.Create();
  {
    [dcc32 Error] Cls.pas(53): E2010 Incompatible types:
    'System.Generics.Collections.TList<Int.IAnotherInterface>' and
    'System.Generics.Collections.TList<Cls.TIAnotherInterface>'
  }
end;

destructor TMainClass.Destroy();
var
  i: Integer;
begin
  (FFunctional as TFunctionalInterface).Free();
  for i := 0 to FAnotherInterface.Count - 1 do
    (FAnotherInterface.Items[i] as TObject).Free;
  (FAnotherInterface as TObject).Free();
  inherited;
end;

function TMainClass.GetFunctional(): IFunctionalInterface;
begin
  Result := FFunctional;
end;

function TMainClass.GetCompGeneric(): TList<IAnotherInterface>;
begin
  Result := FAnotherInterface;
end;

end.


Как правильно это реализовать?
Можно конечно TList объявлять в интерфейсе без указания типа элементов, чего делать не хочется.
Или писать функцию конвертирующую TList<IAnotherInterface> в TList<TIAnotherInterface>, но кажется, должен быть другой более правильный способ.
...
Рейтинг: 0 / 0
19.07.2017, 12:21:59
    #39491479
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
19.07.2017 12:18, SolidSnake пишет:
>
> Строится структура приложения от интерфейсов.

зачем?
какова цель?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.07.2017, 13:07:06
    #39491535
SOFT FOR YOU
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
SolidSnake,

Дженерики - это точно такие же типы как потомки TObject. Потомки TObject ты как будешь передавать?
...
Рейтинг: 0 / 0
19.07.2017, 14:14:10
    #39491592
X-Cite
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
Код: pascal
1.
2.
FAnotherInterface := TList<IAnotherInterface>.Create();
FAnotherInterface.Add(TIAnotherInterface.Create());
...
Рейтинг: 0 / 0
19.07.2017, 14:15:46
    #39491593
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
Использование интерфейсов без необходимости - раскладывание себе (или не дай бог тем, кто после вас будет) грабель на будущее.
...
Рейтинг: 0 / 0
19.07.2017, 14:19:12
    #39491594
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
rgreatИспользование интерфейсов без необходимости - раскладывание себе (или не дай бог тем, кто после вас будет) грабель на будущее.
о дааааа ! При воспоминании об исходниках SAS Планета меня охватывает ужас.
Там вся программа состоит из интерфейсов.
Где надо и где не надо.
Жуть
...
Рейтинг: 0 / 0
19.07.2017, 14:39:53
    #39491609
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
SolidSnakeКак правильно это реализовать?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
unit Int;

interface

type

  .............
  TMyList = TList<>
  // Интерфейс для главного класса
  IMainInterface = interface
    ['{D29A0190-F894-493F-BA97-564C81D49499}']
    function GetFunctional(): IFunctionalInterface;
    function GetCompGeneric(): TMyList;
    property Funtional: IFunctionalInterface read GetFunctional;
    property CompGeneric: TMyList read GetCompGeneric;
  end;
................

unit Cls;

interface

uses
  int;

type

  TMainClass = class(TInterfacedPersistent, IMainInterface)
  private
    FFunctional: IFunctionalInterface;
    FAnotherInterface: TMyList;
    function GetFunctional(): IFunctionalInterface;
    function GetCompGeneric(): TMyList;
  .............
...
Рейтинг: 0 / 0
19.07.2017, 14:56:14
    #39491626
SolidSnake
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
автор Мимопроходящийзачем?
какова цель?
Описание прототипов для классов, методы поля, которые должны быть обязательно реализованы.
Интерфейс декларирует требования к классам.
Приложение будет состоять из блоков, для некоторых интерфейсов будет доступно несколько реализаций.
Причем независимо от реализации, другие части приложения должны свободно работать с ожидаемыми полями и методами любой реализации конкретного интерфейса.

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

Была какая-то проблема с полноценной заменой интерфейсов на абстрактные классы, не могу вспомнить, видимо надо снова пробовать.
Но даже если заменить, то TList<T> все равно потребует точного совпадения типов, основная проблема никуда не уйдет.
X-CiteFAnotherInterface := TList<IAnotherInterface>.Create();
FAnotherInterface.Add(TIAnotherInterface.Create());Очень похоже что это оно :) Искал какое-то сложное решение, но так вполне пойдет, спасибо! (затупил, что называется).

авторПотомки TObject ты как будешь передавать?
Не понял вопрос, это не то? :
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
  TChildClass = class(TFunctionalInterface)
  
  end;

constructor TMainClass.Create();
begin
  // Помещаем в интерфейсное поле FFunctional реализацию TFunctionalInterface
  //FFunctional := TFunctionalInterface.Create();
  FFunctional := TChildClass.Create(); // Сюда подходит и любой потомок
end;



rgreatИспользование интерфейсов без необходимости - раскладывание себе (или не дай бог тем, кто после вас будет) грабель на будущее.Ну пока выглядит всё логично, я задаю минимальные ограничения для реализаций, без которых не могут работать другие блоки.
Т.е. условно блок1 внутри себя видит весь класс1, который реализует интерфейс1.
Но есть блок2, где класс1 даже не виден, туда передается интерфейс и блок2 свободно работает с тем функционалом, который обязательно должен быть реализован.
Проходит время, появляются новые реализации в виде нового класса в блоке1. Но блок2 никак не менялся и должен по прежнему работать. Если схема не сработает, вариант переписать всё в с нуля тоже доступен.
...
Рейтинг: 0 / 0
19.07.2017, 15:05:28
    #39491636
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
имхо, очередная попытка построить "обобщённый решатель абстрактных задач".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.07.2017, 15:06:53
    #39491639
SolidSnake
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
_Vasilisk_ , так не подходит, решение уже есть - выше.
Не подходит потому как в модуле интерфейсов необходимо определить что должно быть внутри TList.
При этом, здесь не должно быть реализаций. И если мы укажем конкретный класс здесь, то снова попадаем на туже самую ситуацию из шапки.
...
Рейтинг: 0 / 0
19.07.2017, 15:15:05
    #39491654
SolidSnake
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
Мимопроходящийимхо, очередная попытка построить "обобщённый решатель абстрактных задач".

Обобщённый абстрактный решатель, но конкретных задач (в блоках решаются конкретные задачи).

Рабочий модуль реализации интерфейса из шапки:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
unit Cls;

interface

uses
  {RTL}
  System.SysUtils,
  System.Contnrs,
  System.Generics.Collections,
  System.Classes,
  int;

type

  // Класс реализующий главный интерфейс IMainInterface
  // Этот класс - единственное, что видно снаружи модуля
  TMainClass = class(TInterfacedPersistent, IMainInterface)
  private
    FFunctional: IFunctionalInterface;
    // Поскольку реализуется интерфейс, TList идет с IAnotherInterface
    FAnotherInterface: TList<IAnotherInterface>;
    function GetFunctional(): IFunctionalInterface;
    function GetCompGeneric(): TList<IAnotherInterface>;
  public
    constructor Create();
    destructor Destroy(); override;
  end;

implementation

type

  // Реализации других интерфейсов
  TFunctionalInterface = class(TInterfacedPersistent, IFunctionalInterface)
    {
      Тут методы, поля.
    }
  end;

  TIAnotherInterface = class(TInterfacedPersistent, IAnotherInterface)
    {
      Тут методы, поля.
    }
  end;

  { MainClass }

constructor TMainClass.Create();
begin
  // Помещаем в интерфейсное поле FFunctional реализацию TFunctionalInterface
  FFunctional := TFunctionalInterface.Create();
  // Теперь надо поместить реализацию в FAnotherInterface, создаем сперва TList
  FAnotherInterface := TList<IAnotherInterface>.Create();
  // Добавляем элемент с конкретной реализацией
  FAnotherInterface.Add(TIAnotherInterface.Create());
end;

destructor TMainClass.Destroy();
var
  i: Integer;
begin
  (FFunctional as TFunctionalInterface).Free();
  for i := 0 to FAnotherInterface.Count - 1 do
    (FAnotherInterface.Items[i] as TObject).Free;
  (FAnotherInterface as TObject).Free();
  inherited;
end;

function TMainClass.GetFunctional(): IFunctionalInterface;
begin
  Result := FFunctional;
end;

function TMainClass.GetCompGeneric(): TList<IAnotherInterface>;
begin
  Result := FAnotherInterface;
end;

end.

...
Рейтинг: 0 / 0
19.07.2017, 15:21:40
    #39491667
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
дерзайте.
до написания "всеобщей теории всего сущего" осталось рукой подать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.07.2017, 15:59:33
    #39491705
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
Мне кажется можно было и классами ограничится.

авторОписание прототипов для классов, методы поля, которые должны быть обязательно реализованы.

Если сильно хочется - можно абстрактный предок создать. Либо частично либо полностью.
...
Рейтинг: 0 / 0
19.07.2017, 16:31:28
    #39491731
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
ТС-у пожалуй было бы невредно почитать Шлеера с Меллором - "моделирование мира в состояниях", 1993 года издания
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.07.2017, 17:20:56
    #39491759
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Generics, Interfaces и реализация
SolidSnakeНе подходит потому как в модуле интерфейсов необходимо определить что должно быть внутри TList.Так и не понял, почему не подходит? Я говорю, что Вам всего лишь, нужно ЯВНО определить тип TList<IAnotherInterface>
SolidSnakeПри этом, здесь не должно быть реализацийНикакой реализации и нет
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Generics, Interfaces и реализация / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]