Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
Доброго дня, коллеги.
первый вариант интерфейса
IConfigController = interface(IInterface)
    procedure Load(const AType: string; ADest: TMemIniFile); stdcall;
    function Save(const AType: string; ASource: TMemIniFile): boolean;  stdcall;
  end;

и объявление в классе
{IConfigController}
    procedure IConfigController.Load = LoadConfigFile;
    function IConfigController.Save =  SaveConfigFile;
    procedure LoadConfigFile(const AType: string; ADest: TMemIniFile); stdcall;
    function SaveConfigFile(const AType: string; ASource: TMemIniFile): boolean;  stdcall;

Второй вариант интерфейса
IConfigController = interface(IInterface)
    procedure Load(const AType: string; ADest: TStrings);overload; stdcall;
    function Save(const AType: string; ASource: TStrings): boolean; overload; stdcall;
    procedure Load(const AType: string; ADest: TMemIniFile);overload; stdcall;
    function Save(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;
  end;

и объявление в классе
{IConfigController}
    procedure IConfigController.Load = LoadConfigFile;
    function IConfigController.Save =  SaveConfigFile;
    procedure LoadConfigFile(const AType: string; ADest: TStrings);overload; stdcall;
    function SaveConfigFile(const AType: string; ASource: TStrings): boolean; overload; stdcall;
    procedure LoadConfigFile(const AType: string; ADest: TMemIniFile);overload; stdcall;
    function SaveConfigFile(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;

Понятно, что компилятор пошлет в пеший тур ибо замыкание функций на интерфейс не корректно.
Именование функций в интерфейсе нужно оставить именно таким. В классе тоже, т.к. он здоровый и всяких load/save там куча
Без костыля в виде отдельного класса никак?
7 дек 17, 11:41    [21014241]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
wadman
Member

Откуда: Санкт-Петербург
Сообщений: 23220
Что мешает вместо Load использовать более осмысленное название процедуры (ConfigLoad)?
7 дек 17, 11:45    [21014256]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
AX-Class
Member

Откуда:
Сообщений: 100
Олег Третьяков,
Т.е., как заменить
procedure IConfigController.Load = LoadConfigFile;
на
procedure Load(const AType: string; ADest: TStrings);overload; stdcall;
...
procedure Load(const AType: string; ADest: TStrings);
begin
  LoadConfigFile(AType, ADest);
end;

но, чтоб было меньше букв?
7 дек 17, 11:52    [21014281]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
wadman,
на мой взгляд не комильфо далее будет ConfigController.configLoad. дважды config - как то не айс
AX-Class,
Речь идет о синтаксисе замыкания перегруженных функций в интерфейсе на их псевдонимы реализации в классе. И да, чтоб меньше букв)
7 дек 17, 12:08    [21014381]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
GunSmoker
Member

Откуда:
Сообщений: 2929
Олег Третьяков, а зачем в классе нужен именно overload Load/SaveConfigFile?
7 дек 17, 12:49    [21014688]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
GunSmoker,
Именно overload?.. В классе?....
Мм.. не уловил изюмину вопроса.
Я правда уже поломал код и нарисовал класс-костыль.
7 дек 17, 13:07    [21014794]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
GunSmoker,
Пес ними, именами, но сигнатуры разве не должны совпадать в интерфейсе и в классе?
7 дек 17, 13:17    [21014859]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
GunSmoker
Member

Откуда:
Сообщений: 2929
Олег Третьяков, я, мож, вопрос не уловил, но:
    procedure LoadConfigFile1(const AType: string; ADest: TStrings); stdcall;
    function SaveConfigFile1(const AType: string; ASource: TStrings): boolean; stdcall;
    procedure LoadConfigFile2(const AType: string; ADest: TMemIniFile); stdcall;
    function SaveConfigFile2(const AType: string; ASource: TMemIniFile): boolean; stdcall;
    procedure IConfigController.Load = LoadConfigFile1;
    function IConfigController.Save =  SaveConfigFile1;
    procedure IConfigController2.Load = LoadConfigFile2;
    function IConfigController2.Save =  SaveConfigFile2;
7 дек 17, 13:55    [21015006]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Dimonka
Member

Откуда:
Сообщений: 952
Ещё можно подумать в другом направлении, например можно сделать класс-адаптер для разных типов источника данных, а Load/Save сделать работающим с адаптером. Тогда в классе достаточно оставить методы Load/Save:
IConfigController = interface(IInterface)
    procedure Load(const AType: string; ADest: TMyDataSource); stdcall;
    function Save(const AType: string; ASource: TMyDataSource): boolean;  stdcall;
  end;
А уже в TMyDataSource прописать работу с разными источниками данных.
7 дек 17, 13:59    [21015030]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
GunSmoker,
Это разнос на два интерфейса.
Ну да, не уловил.
Хочу реализовать в одном интерфейсе более одного вариантов функции. В классе именовать с префиксом имени интерфейса.
7 дек 17, 14:06    [21015053]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
Dimonka,
Не хотел городить адаптер, видимо придется, с маршрутизацией через QueryInterface. Благо используемого функционала, теперь уже владельца, не много.
офф: торможу с участием, т.к. сегодня баги с электричеством офисе, бесперебойники пищат, приходится выключаться.
7 дек 17, 14:32    [21015192]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Кар-Кар
Guest
Очевидно не работает.
Может хаком тогда, дублирование. Внутри юнита, где класс реализовывается делаем копипаст здорового интерфейса и..

IConfigController = interface(IInterface)
['{F4BAACCE-328C-4038-8184-DE1ACECF881E}']
  procedure Load_Strings(const AType: string; ADest: TStrings);overload; stdcall;
  function Save_Strings(const AType: string; ASource: TStrings): boolean; overload; stdcall;
  procedure Load_Ini(const AType: string; ADest: TMemIniFile);overload; stdcall;
  function Save_Ini(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;
end;
Его и реализуем, наружу хард кастим. Главное чтоб GUID был одинаковым!
7 дек 17, 14:50    [21015260]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Кар-Кар
Guest
Т.е. будет внутри скрытый интерфейс с тем же GUID и нужным именованием методов:
IConfigControllerInternal = interface(IInterface)
['{F4BAACCE-328C-4038-8184-DE1ACECF881E}']
  procedure IConfigController_Load(const AType: string; ADest: TStrings);overload; stdcall;
  function IConfigController_Save(const AType: string; ASource: TStrings): boolean; overload; stdcall;
  procedure IConfigController_Load(const AType: string; ADest: TMemIniFile);overload; stdcall;
  function IConfigController_Save(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;
end;

TMyClass = class(TInterfacedObject, IConfigControllerInternal)
public
  procedure IConfigController_Load(const AType: string; ADest: TStrings);overload; stdcall;
  function IConfigController_Save(const AType: string; ASource: TStrings): boolean; overload; stdcall;
  procedure IConfigController_Load(const AType: string; ADest: TMemIniFile);overload; stdcall;
  function IConfigController_Save(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;
end;

function CreateConfigController:IInterface;
begin
TConfigController.Create.QueryInterface(IConfigController{IConfigControllerInternal},Result);
end;

exports
CreateConfigController;

А снаружи для человеков будет:
IConfigController = interface(IInterface)
['{F4BAACCE-328C-4038-8184-DE1ACECF881E}']
  procedure Load(const AType: string; ADest: TStrings);overload; stdcall;
  function Save(const AType: string; ASource: TStrings): boolean; overload; stdcall;
  procedure Load(const AType: string; ADest: TMemIniFile);overload; stdcall;
  function Save(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;
end;

function CreateConfigController:IConfigController;external 'MyLib.dll';

VMT совпадает, главное держать синхронно оба в случае изменений.
7 дек 17, 15:07    [21015368]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
Кар-Кар,
В топку поддержание синхронности)
Вынес в отдельный класс, имхо меньшее зло
+
TConfigController = class(TComponent,
                            IConfigController)
   public
    procedure Load(const AType: string; ADest: TMemoryStream);overload; stdcall;
    function Save(const AType: string; ASource: TMemoryStream): boolean; overload; stdcall;
    procedure Load(const AType: string; ADest: TStrings);overload; stdcall;
    function Save(const AType: string; ASource: TStrings): boolean; overload; stdcall;
    procedure Load(const AType: string; ADest: TMemIniFile);overload; stdcall;
    function Save(const AType: string; ASource: TMemIniFile): boolean; overload; stdcall;
  end;

в классе-владельце
function TBaseClass.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if IsEqualGUID(IID, IConfigController) then
  begin
    if Assigned(fConfigController) then
      Result := fConfigController.QueryInterface(IID, Obj)
    else
      Result := E_NOINTERFACE;
    Exit;
  end else
    Result := inherited QueryInterface(IID, Obj);
end;
7 дек 17, 15:34    [21015460]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
Олег Третьяков
в классе-владельце
А почему бы не сделать через property implements? Смысл тот же, а кода меньше. И в новых делфях QueryInterface будет работать в обе стороны
7 дек 17, 15:42    [21015491]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
_Vasilisk_,
Привычка.
Да, можно, согласен.
_Vasilisk_
И в новых делфях QueryInterface будет работать в обе стороны

Эм, интересно. Даже рекурсии не возникает? Можно ссылко с деталями?
7 дек 17, 16:04    [21015604]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9916
Олег Третьяков
Можно ссылко с деталями?
тынц
7 дек 17, 17:53    [21016079]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Hammer
Member

Откуда: Москва
Сообщений: 471
Типа так?:
+

unit UConfigController;

interface

uses Classes, IniFiles;

type
  IConfigController = interface(IInterface)
    ['{0D874EC8-386A-4CB8-B37B-34FD485BEC98}']
    procedure LoadMemIniFile(const AType: string; ADest: TMemIniFile); stdcall;
    function SaveMemIniFile(const AType: string; ASource: TMemIniFile): boolean; stdcall;
    procedure LoadStrings(const AType: string; ADest: TStrings); stdcall;
    function SaveStrings(const AType: string; ASource: TStrings): boolean; stdcall;
    procedure Load(const AType: string; ADest: TObject); stdcall;
    function Save(const AType: string; ASource: TObject): boolean; stdcall;
  end;

  TConfigController = class(TInterfacedObject,
                            IConfigController)
  private
    procedure LoadMemIniFile(const AType: string; ADest: TMemIniFile); stdcall;
    function SaveMemIniFile(const AType: string; ASource: TMemIniFile): boolean; stdcall;
    procedure LoadStrings(const AType: string; ADest: TStrings); stdcall;
    function SaveStrings(const AType: string; ASource: TStrings): boolean; stdcall;
  public
    procedure Load(const AType: string; ADest: TObject); stdcall;
    function Save(const AType: string; ASource: TObject): boolean; stdcall;
  public
    class function GetConfigController: IConfigController;
  end;

implementation

{ TConfigController }

class function TConfigController.GetConfigController: IConfigController;
begin
  Result := TConfigController.Create;
end;

procedure TConfigController.Load(const AType: string; ADest: TObject);
begin
  if ADest.InheritsFrom(TMemIniFile) then
    LoadMemIniFile(AType, TMemIniFile(ADest))
  else
    if ADest.InheritsFrom(TStrings) then
      LoadStrings(AType, TStrings(ADest))
end;

procedure TConfigController.LoadMemIniFile(const AType: string;
  ADest: TMemIniFile);
begin
//
end;

procedure TConfigController.LoadStrings(const AType: string; ADest: TStrings);
begin
//
end;

function TConfigController.Save(const AType: string; ASource: TObject): boolean;
begin
  Result := False;
  if ASource.InheritsFrom(TMemIniFile) then
    Result := SaveMemIniFile(AType, TMemIniFile(ASource))
  else
    if ASource.InheritsFrom(TStrings) then
      Result := SaveStrings(AType, TStrings(ASource))
end;

function TConfigController.SaveMemIniFile(const AType: string;
  ASource: TMemIniFile): boolean;
begin
  Result := False;
end;

function TConfigController.SaveStrings(const AType: string;
  ASource: TStrings): boolean;
begin
  Result := False;
end;

end.

12 дек 17, 10:39    [21026113]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
Hammer,
Нет. см. выше.
12 дек 17, 16:56    [21028001]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Hammer
Member

Откуда: Москва
Сообщений: 471
Олег Третьяков
Hammer,
Нет. см. выше.

Хозяин-барин.
Надеюсь, что он в курсе того, что TComponent не поддерживает подсчет ссылок.
12 дек 17, 19:37    [21028546]     Ответить | Цитировать Сообщить модератору
 Re: Интерфейс с перегруженными функциями и его реализация  [new]
Олег Третьяков
Member

Откуда: Волгоград
Сообщений: 116
Hammer,
Есно)
12 дек 17, 21:00    [21028668]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить