Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Implementierung einer Interface Prozedur (https://www.delphipraxis.net/182116-implementierung-einer-interface-prozedur.html)

Gutelo 2. Okt 2014 00:21

Implementierung einer Interface Prozedur
 
Hallo,

ich habe eine selbstgeschriebene Komponente. Diese Komponente enthaelt eine Listbox, welche als Items die Dateinamen von Dateien in einem bestimmten Verzeichnis enthaelt. Nun moechte ich innerhalb der Komponente soetwas wie folgende Prozedur haben:

Procedure DoWithFile(Filename : String);

Diese Procedure soll von einer andere Procedure innerhalb der Komponente aufgerufen werden, in etwa soetwas:

Procedure AndereProzedur();
begin
DoWithFile(LV.items[1]);
end;

Nun die Frage. Wie muss ich DoWithFile deklarieren so dass ich sie im Hauptprogramm (das die Komponente verwendet) implementieren kann? In Java waere das soetwas wie ein Interface.

Gutelo

Sir Rufo 2. Okt 2014 01:26

AW: Implementierung einer Interface Prozedur
 
Möchtest du einen Event haben?

Dejan Vu 2. Okt 2014 08:06

AW: Implementierung einer Interface Prozedur
 
Du kannst das mit einem Interface, mit einer Action (Reference to procedure) oder mit einem Event machen. Hier würde ich persönlich ein Interface vorziehen, der Intention entsprechend.

Blup 2. Okt 2014 09:53

AW: Implementierung einer Interface Prozedur
 
Ein Interface scheint eigentlich schon zu viel Aufwand.
Delphi-Quellcode:
TProzessFileEvent = procedure(Sender: TObject; const AFilename: string) of object;

TMyComponent = class({...})
public
  procedure DoProzessFileList(AProzessFileEvent: TProzessFileEvent);
end;

procedure TMyComponent.DoProzessFileList(AProzessFileEvent: TProzessFileEvent);
var
  Filename: string;
begin
  Assert(Assigned(AProzessFileEvent), Self.Name + '.DoProzessFileList(nil)');

  for Filename in FFileList do
    AProzessFileEvent(Self, Filename);
end;
Eine mögliche Erweiterung für den Objektinspektor:
Delphi-Quellcode:
TMyComponent2 = class(TMyComponent)
private
  FOnProcessFile: TProzessFileEvent;
public
  procedure DoProzessFileList; reintroduce;
published
  property OnProcessFile: TProzessFileEvent read FOnProcessFile write FOnProcessFile;
end;

procedure TMyComponent2.DoProzessFileList;
begin
  if Assigned(FOnProcessFile) then
    inherited DoProzessFileList(FOnProcessFile);
end;
Den Auslöser(Sender) als Parameter mitzuliefern ist langfristig immer eine gute Idee.

Gutelo 2. Okt 2014 15:26

AW: Implementierung einer Interface Prozedur
 
Hallo,

allen vielen Dank fuer die Antworten. Blup, die Version sieht ganz gut aus und an Funktionsvariable habe ich auch schon gedacht. Allerdings wuerde ich anstatt einer eigenen Prozedur namens TMyComponent.DoProzessFileList(AProzessFileEvent: TProzessFileEvent); gerne den Aufruf aus dem OnClick Ereignis des Listviews ausfuehren. Wuerde folgendes gehen?:

Delphi-Quellcode:
TProzessFileEvent = procedure(AFilename: string) of object;

TMyComponent = class({...})
public
  VmyEvent : TProzessFileEvent;
  procedure SetMyProzessFileEvent(PFE : TProcessFileEvent);
  procedure OnClickListView(AProzessFileEvent: TProzessFileEvent);
end;

procedure TMyComponent.SetMyProzessFileEvent(PFE : TProcessFileEvent);
begin
  VmyEvent := PFE;
end;

procedure TMyComponent.OnClickListView(Sender: TObject);
var
  Filename: string;
  Li : TListItem;
begin
  Li := ListView1.selected;
  Filename := Li.caption;
  VMyEvent(Filename);
end;
Gutelo


Edit: Funktioniert prima, danke !!!!

Dejan Vu 2. Okt 2014 16:09

AW: Implementierung einer Interface Prozedur
 
Hier werden 'Events' verwendet, wo doch gar kein Ereignis eintritt. Nun ja.
Zitat:

Zitat von Blup (Beitrag 1274551)
Ein Interface scheint eigentlich schon zu viel Aufwand.

Aufwand? Du meinst Tippaufwand? Na wenn Du danach die richtige Vorgehensweise wählst... ;-)

Die Lösung mit dem Interface finde ich besser, weil erweiterbar. Eine Methode (die sich hinter dem 'Event' bzw. der Methodenvariablen) kann man nur aufblähen, aber ein Interface kann man erweitern.

sx2008 3. Okt 2014 12:49

AW: Implementierung einer Interface Prozedur
 
Zitat:

Zitat von Dejan Vu (Beitrag 1274660)
Aufwand? Du meinst Tippaufwand? ...
Die Lösung mit dem Interface finde ich besser, weil erweiterbar.

Wenn man in Delphi ein Interface implementieren möchte dann muss man von einer kleinen Auswahl von Basisklassen (TInterfacedObject, TComObject, TTypedComObject, TAutoObject, TAutoIntfObject) ableiten.
(Oder man muss die Methoden QueryInterface(), _AddRef() und _Release() selbst implementieren)

Dies ist schon mal eine ganz erhebliche Einschränkung weil man nicht einfach von einer x-beliebigen Klasse ableiten kann und dann zusätzlich das Interface implementiert.

Aber es kommt noch schlimmer!
Es dürfte bekannt sein, dass wenn man in Delphi mit einem Objekt arbeitet und dabei den Objektzeiger als auch den Interfacezeiger benützt man in Teufels Küche kommt.
Entweder ruft man die Methode Free() auf obwohl der Interfacezeiger noch benützt wird.
=> Zugriff über den Interfacezeiger auf ein freigegebene Objekt
oder der Referenzzähler geht auf 0 und das Objekt wird freigegeben obwohl der Objektzeiger noch benützt wird
=> Zugriff über den Objektzeiger auf ein freigegebene Objekt

In C# ist das kein Problem weil die Lebenszeit der Objekte über eine Garbage Collection bestimmt wird.
In Delphi darf man aber nur über den Interfacezeiger oder den Objektzeiger arbeiten, niemals mit beiden gleichzeitig!

Ein Event hat in Delphi weniger Einschränkungen und ist weniger aufwändig.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz