![]() |
Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Hallo Forum,
lang ists her das ich hier mal was gepostet habe :) Da ich aber jetzt wieder vermehrt mit Delphi arbeite würde ich gerne mal eine Frage stellen. Ich habe eine Klasse geschrieben, die abgeleitet von TThread ist und ein Interface implementiert, so als Beispiel:
Code:
Bei TZweiteKlasse gelingt folgender aufruf, bei TMeineKlasse leider nicht, woran kann es liegen?
type
TMeineKlasse = Class(TThread, IInterfaceMein) end; TZweiteKlasse = Class(TInterfacedObjekt, IInterfaceZwei) end;
Code:
Gibt es irgendwas einfaches das ich vergessen habe? Oder liegt es daran das eine Klasse von TTHread abgeleitet wurde?
var
meinInterface: IInterfaceMein; zweiInterface: IInterfaceZwei; begin meinInterface := TMeineKlasse.Create AS IInterfaceMein; // Operator ist auf Operand nicht anwendbar zweiInterface := TZweiteKlasse AS IInterfaceZwei; // Geht end; Mfg, Mika |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Da das IInterfaceMein implizit von IInterface abgeleitet ist, gehören dazu natürlich auch Implementierungen der dort deklarierten Methoden - insbesondere QueryInterface! Da der Compiler schon viel eher meckern würde, wenn diese Methoden nicht in deiner TThread-Ableitung enthalten wären, denke ich daß du die auch tatsächlich implementiert hast.
Wenn du jetzt dem Compiler sagst, daß dein TThread-Abkömmling das IInterface tatsächlich implementiert, sollte es auch gehen:
Delphi-Quellcode:
TMeineKlasse = Class(TThread, IInterface, IInterfaceMein)
|
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Wenn du das IInterface selber einbindest, dann mußt du natürlich auch die Methoden dieses Interfaces selber implementieren,
aber dafür kannst'e dir auch einfach alles Nötige aus dem TInterfacedObject rauskopieren. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Hei,
danke erstmal für die Antworten. Die Methoden des Interfaces habe ich eingebunden :) Hier mal zur besseren Verständnis richtiger Code: Das Problem ist das gleiche, nur das man das AUgenmerk auf TDeviceController legt. Interfaces
Code:
TLineController
type
{ Forwardeklarationen } IDeviceController = interface; IDeviceEntity = interface; { Interface unserer obersten Controllerklasse } ILineController = interface(IInterface)['{4096970D-4269-4626-B710-AF753D80D0BF}'] { Initialisiert den Controller mit den gegebenen Daten } function Initialize(db: TAdsConnection; id: Integer): Boolean; { Finalisiert den Controller, entfernt alle Daten } function Finalize: Boolean; { Setzt die Genauigkeit der Protokollierung } function SetLoglevel(ll: Integer): Boolean; { Gibt die Datenbankverbindung zurueck die angegeben wurde } function GetDatabaseConnection: TAdsConnection; function GetDatabaseConfigurationKey: Integer; { Setzt die Callbackmethode die der Controller aufrufen soll } function SetCallbackMethod(cm: TCallbackMethod): Boolean; { Verarbeitet einen DeviceStatus und reicht ihn an den Callback weiter } function ProcessDeviceStatus(ds: TDeviceStatus): Boolean; { Gibt die Anzahl der DeviceController zurück } function GetDeviceControllerCount: Integer; { Gibt den Index des übergebenen DeviceControllers wieder } function GetDeviceControllerIndex(dc: IDeviceController): Integer; { Gibt den DeviceController des übergebenen Index wieder } function GetDeviceControllerByIndex(index: Integer): IDeviceController; { Fügt einen neuen DeviceController hinzu } function AddDeviceController(dc: IDeviceController): Boolean; { Entfernt den übergebenen DeviceController } function RemoveAllDeviceController: Boolean; function RemoveDeviceController(index: Integer): Boolean; overload; function RemoveDeviceController(dc: IDeviceController): Boolean; overload; { Startet den übergebenen DeviceController } function StartAllDeviceController: Boolean; function StartDeviceController(index: Integer): Boolean; overload; function StartDeviceController(dc: IDeviceController): Boolean; overload; { Stoppt den übergebenen DeviceController } function StopAllDeviceController: Boolean; function StopDeviceController(index: Integer): Boolean; overload; function StopDeviceController(dc: IDeviceController): Boolean; overload; { Aktiviert den übergebenen DeviceController, somit wird er bei der Abfrage der DeviceController mit einbezogen } function ActivateAllDeviceController: Boolean; function ActivateDeviceController(index: Integer): Boolean; overload; function ActivateDeviceController(dc: IDeviceController): Boolean; overload; { Deaktiviert den übergebenen DeviceController, somit wird er bei der Abfrage der DeviceController übersprungen } function DeactivateAllDeviceController: Boolean; function DeactivateDeviceController(index: Integer): Boolean; overload; function DeactivateDeviceController(dc: IDeviceController): Boolean; overload; end; { Interface unserer Controllerklasse für die einzelnen Verbindungen/Module } IDeviceController = interface(IInterface)['{0217D970-51CC-49AD-944E-E9B0B86C6C14}'] { Initialisiert den Controller mit den gegebenen Daten } function Initialize(lc: ILineController; id: Integer): Boolean; { Finalisiert den Controller, entfernt alle Daten } function Finalize: Boolean; { Setzt die Genauigkeit der Protokollierung } function SetLoglevel(ll: Integer): Boolean; { Setzt den LineController dieses Objekts, wichtig um Daten weiterzugeben } function SetLineController(lc: ILineController): Boolean; { Gibt den LineController dieses Objektszurück } function GetLineController: ILineController; { Setzt die Verbindung dieses Controllers, also Comport oder TCP/IP } function SetConnection(cnnct: IPort): Boolean; { Ermittelt die Verbindung dieses Controllers } function GetConnection: IPort; { Oeffnet die Verbindung } function OpenConnection(ps: TPortSettings): Boolean; { Schliesst die Verbindung } function CloseConnection: Boolean; { Liest von der Verbindung } function ReadConnection: String; overload; function ReadConnection(ByteCount: Integer): String; overload; { Schreibt auf die Verbindung } function WriteConnection(Text: String): Boolean; { Aktiviert den Controller, heisst er soll arbeiten falls gefragt } function Activate: Boolean; { Deaktiviert den Controller, Controller arbeitet nicht } function Deactivate: Boolean; { Startet die Abfrage der einzelnen Module die angeschlossen sind } function Start: Boolean; { Beendet die Abfrage der einzelnen Module die angeschlossen sind } function Stop: Boolean; { Gibt die Anzahl der angeschlossenen DeviceEntities zurück } function GetDeviceEntityCount: Integer; { Gibt den Index des übergebenen DeviceEntity wieder } function GetDeviceEntityIndex(de: IDeviceEntity): Integer; { Gibt das DeviceEntity des übergebenen Index wieder } function GetDeviceEntityByIndex(index: Integer): IDeviceEntity; { Fügt ein neues DeviceEntity hinzu } function AddDeviceEntity(de: IDeviceEntity): Boolean; { Entfernt das übergebene DeviceEntity } function RemoveAllDeviceEntitites: Boolean; function RemoveDeviceEntity(index: Integer): Boolean; overload; function RemoveDeviceEntity(de: IDeviceEntity): Boolean; overload; { Aktiviert das übergebenen DeviceEntity, somit wird es bei der Abfrage der DeviceEntities mit einbezogen } function ActivateAllDeviceEntities: Boolean; function ActivateDeviceEntity(index: Integer): Boolean; overload; function ActivateDeviceEntity(de: IDeviceEntity): Boolean; overload; { Dektiviert das übergebenen DeviceEntity, somit wird es bei der Abfrage der DeviceEntities ausgelassen } function DeactivateAllDeviceEntities: Boolean; function DeactivateDeviceEntity(index: Integer): Boolean; overload; function DeactivateDeviceEntity(de: IDeviceEntity): Boolean; overload; end; IDeviceEntity = interface(IInterface)['{E7803FED-19E9-462C-9289-2165E0464F53}'] { Initialisiert den Controller mit den gegebenen Daten } function Initialize(lc: ILineController; dc: IDeviceController; id: Integer): Boolean; { Finalisiert den Controller, entfernt alle Daten } function Finalize: Boolean; { Setzt die Genauigkeit der Protokollierung } function SetLoglevel(ll: Integer): Boolean; { Setzt den LineController dieses Objekts, wichtig um Daten weiterzugeben } function SetLineController(lc: ILineController): Boolean; { Setzt den DeviceController dieses Objekts, wichtig um Daten weiterzugeben } function SetDeviceController(dc: IDeviceController): Boolean; { Gibt den LineController dieses Objekts wieder } function GetLineController: ILineController; { Gibt den DeviceController dieses Objekts wieder } function GetDeviceController: IDeviceController; { Aktiviert das modul, heisst er soll arbeiten falls gefragt } function Activate: Boolean; { Deaktiviert das Modul, Modul arbeitet nicht } function Deactivate: Boolean; { Liest den aktuellen Gerätestatus aus } function GetDeviceStatus: TDeviceStatus; { Setzt den aktuellen Gerätestatus. } function SetDeviceStatus(ds: TDeviceStatus): Boolean; { Setzt das Relais auf den angegebenen Status, falls vorhanden } function SetRelaisState(ns: Boolean): Boolean; { Schreibt den gegebenen Text auf das Display, falls vorhanden } function SetDisplayText(nt: String): Boolean; { Hat das Geraet die angegebene Eigenschaft? } function IsRfidModule: Boolean; function IsDisplayModule: Boolean; function IsRelaisModule: Boolean; function IsScannerModule: Boolean; function IsNumpadModule: Boolean; end;
Code:
TDeviceController
TLineController = class (TInterfacedObject, ILineController)
private // Logger dieser Klasse Logfile: TFCSLogging; // Die Verbindung zu unserer Datenbank DBConnection: TAdsConnection; // Die CallbackMethode die vom Aufrufer gesetzt werden kann CallbackMethod: TCallbackMethod; // Konfigurationsschluessel in der Datenbank ConfigurationKey: Integer; // Die Liste mit unseren DeviceControllern DeviceControllers: TInterfaceList; // Der Titel dieses LineControllers Titel: String; // Legt die zu dieser Konfiguration gehörenden Unterobjekte an function InitializeComponents: Boolean; // Erstellt einen Thread der die CallbackMethode ausfuehrt falls angegeben function ExecuteCallback(ds: TDeviceStatus): Boolean; // Speichert einen Gerätestatus in der Datenbank function PushDeviceStatusToDatabase(ds: TDeviceStatus): Boolean; public // Standardkonstruktor dieser Klasse constructor Create; // Standarddestruktor dieser Klasse destructor Destroy; reintroduce; // Aus dem Interface geerbte Methoden function Initialize(db: TAdsConnection; id: Integer): Boolean; function Finalize: Boolean; function SetLoglevel(ll: Integer): Boolean; function GetDatabaseConnection: TAdsConnection; function GetDatabaseConfigurationKey: Integer; function SetCallbackMethod(cm: TCallbackMethod): Boolean; function ProcessDeviceStatus(ds: TDeviceStatus): Boolean; function GetDeviceControllerCount: Integer; function GetDeviceControllerIndex(dc: IDeviceController): Integer; function GetDeviceControllerByIndex(index: Integer): IDeviceController; function AddDeviceController(dc: IDeviceController): Boolean; function RemoveAllDeviceController: Boolean; function RemoveDeviceController(index: Integer): Boolean; overload; function RemoveDeviceController(dc: IDeviceController): Boolean; overload; function StartAllDeviceController: Boolean; function StartDeviceController(index: Integer): Boolean; overload; function StartDeviceController(dc: IDeviceController): Boolean; overload; function StopAllDeviceController: Boolean; function StopDeviceController(index: Integer): Boolean; overload; function StopDeviceController(dc: IDeviceController): Boolean; overload; function ActivateAllDeviceController: Boolean; function ActivateDeviceController(index: Integer): Boolean; overload; function ActivateDeviceController(dc: IDeviceController): Boolean; overload; function DeactivateAllDeviceController: Boolean; function DeactivateDeviceController(index: Integer): Boolean; overload; function DeactivateDeviceController(dc: IDeviceController): Boolean; overload; end;
Code:
TDeviceEntity, IPort und so weiter sollten in dem Kontext keine Rolle spielen denk ich mal...
type
TDeviceController = class (TThread, IDeviceController) private // Referenzzaehler dieses InterfacedObjekts FRefCount: Integer; // Logger dieser Klasse Logfile: TFCSLogging; // Konfigurationsschluessel in der Datenbank ConfigurationKey: Integer; // LineController dem dieser DeviceController untergeordnet ist LineController: ILineController; // Verbindung die dieser DeviceController bereitstellt Port: IPort; // Die Liste mit unseren DeviceEntities DeviceEntities: TInterfaceList; // Der Titel dieses LineControllers Titel: String; // Ist der Controller aktiv? Sollen Geräte abgefragt werden? Aktiv: Boolean; // Zeit in Millisekunden zwischen zwei Abfragen DelayMSecs: Integer; // Methoden die Klassen benoetigen die ein Interface implementieren function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; // Legt die zu dieser Konfiguration gehörenden Unterobjekte an function InitializeComponents: Boolean; protected procedure Execute; override; public property RefCount: Integer read FRefCount; // Standardkonstruktor dieser Klasse constructor Create; reintroduce; // Standarddestruktor dieser Klasse destructor Destroy; reintroduce; // Aus dem Interface geerbte Methoden function Initialize(lc: ILineController; id: Integer): Boolean; function Finalize: Boolean; function SetLoglevel(ll: Integer): Boolean; function SetLineController(lc: ILineController): Boolean; function GetLineController: ILineController; function SetConnection(cnnct: IPort): Boolean; function GetConnection: IPort; function OpenConnection(ps: TPortSettings): Boolean; function CloseConnection: Boolean; function ReadConnection: String; overload; function ReadConnection(ByteCount: Integer): String; overload; function WriteConnection(Text: String): Boolean; function Activate: Boolean; function Deactivate: Boolean; function Start: Boolean; function Stop: Boolean; function GetDeviceEntityCount: Integer; function GetDeviceEntityIndex(de: IDeviceEntity): Integer; function GetDeviceEntityByIndex(index: Integer): IDeviceEntity; function AddDeviceEntity(de: IDeviceEntity): Boolean; function RemoveAllDeviceEntitites: Boolean; function RemoveDeviceEntity(index: Integer): Boolean; overload; function RemoveDeviceEntity(de: IDeviceEntity): Boolean; overload; function ActivateAllDeviceEntities: Boolean; function ActivateDeviceEntity(index: Integer): Boolean; overload; function ActivateDeviceEntity(de: IDeviceEntity): Boolean; overload; function DeactivateAllDeviceEntities: Boolean; function DeactivateDeviceEntity(index: Integer): Boolean; overload; function DeactivateDeviceEntity(de: IDeviceEntity): Boolean; overload; end; JKetzt möchte ich halt in einer Methode von TLineController folgendes machen können:
Code:
aber das geht wie gesagt nicht und ich könnte mir das nur erklären weil DeviceController halt von TThread abgeleitet ist.
var
meinDevice: IDeviceController; begin meinDevice := TDeviceController.Create AS IDeviceController; end; |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Ich wiederhole:
type TDeviceController = class (TThread, IInterface, IDeviceController) |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Danke für den Tipp Herr Raabe, ich werd das morgen mal ausprobieren.
Ich hab gedacht da IDeviceController schon IInterface implementiert, hat TDeviceController das dadurch auch. Ich war mir nicht sicher ob das bei den Interfaces in Delphi mitvererbt wird. Deswegen hatte ich auch folgende Zeilen in TDeviceController aufgenommen.
Code:
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; Schönen Abend noch. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Zitat:
Schau mal wie
Delphi-Quellcode:
TInterfacedObject
![]() |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Ich glaube, du mutest deiner Thread-Klasse zuviel zu.
Anstatt das Interface IDeviceController zu implementieren würde es doch ausreichen, wenn die Threadklasse von Aussen eine Instanz von IDeviceController zugewiesen bekommt. Hier mal stark vereinfacht die Unterschiede:
Delphi-Quellcode:
Mein Vorschlag hat den Vorteil, dass er einfacher umzusetzen ist und ausserdem wird das Interface IDeviceController von einer eigenen Klasse implementiert.
// dein Vorschlag
TDeviceController = class(TThread, IDeviceController) private // hier müssen alle Methoden von IDeviceController implementiert werden ... public procedure Execute;override; end; // ====================================================================== // mein Vorschlag TDeviceThread = class(TThread) public // "DeviceController" muss von Aussen übergeben werden und danach // der Thread mit Resume() gestartet werden DeviceController : IDeviceController; procedure Execute;override; // benützt "DeviceController" end; Diese bedeutet, dass dein Code zunächst auch ohne Multithreading testbar ist. Erst später kommt eine (oder mehrere!) Threadklasse hinzu, der schon bestehenden Code im Kontext eines Threads ausführt. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Zitat:
Delphi-Quellcode:
unterstützt IDeviceController aber nicht IInterface,
TMyClass = class(TObject, IDeviceController)
Delphi-Quellcode:
unterstützt IInterface und IDeviceController.
TMyClass = class(TObject, IInterface, IDeviceController)
Natürlich wird Interface-Unterstützungg vererbt. Deswegen funktioniert auch
Delphi-Quellcode:
.
TMyClass = class(TInterfacedObject, IDeviceController)
Das erste mag etwas verwundern, wenn man Interface-Vererbung (die ähnlich wie Klassenvererbung funktioniert) und Interface-Unterstützung (das was man mit Supports bzw. QueryInterface abfragt) nicht auseinanderhält. Es handelt sich aber hierbei um zwei verschiedene Dinge. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Okai, das hat funktioniert. Danke euch für eure Hilfe!
|
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Zitat:
Eine Threadklasse darf kein Interface eines ![]() Im Moment mag deine Lösung funktionieren; später wirst du merken, dass da etwas nicht richtig läuft. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Ich werd mir deinen Vorschlag mal durch den Kopf gehen lassen, danke für den Hinweis.
|
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Zitat:
ich bin über diesen Beitrag gestoßen, da ich ein Interface in einem Thread nutzen möchte. Dazu habe ich versucht das oben zitierte umzusetzen. Wie folgt sieht mein Beispiel aus:
Delphi-Quellcode:
Jedoch kommt es zu folgenden Meldungen:
unit Unit2;
interface uses Classes; type IMyInterface = Interface(IInterface) procedure setstate; function getstate(): Boolean; property State: Boolean read getstate write setstate; End; TMyThread = class(TThread, IInterface, IMyInterface) private { Private-Deklarationen } protected procedure Execute; override; end; implementation [DCC Fehler] Unit2.pas(15): E2003 Undeklarierter Bezeichner: 'QueryInterface' [DCC Fehler] Unit2.pas(15): E2003 Undeklarierter Bezeichner: '_AddRef' [DCC Fehler] Unit2.pas(15): E2003 Undeklarierter Bezeichner: '_Release' Muss ich diese Methoden doch selbst implementieren? Bin davon ausgegangen, dass diese vererbt werden. Vielen Dank. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Zitat:
Das Interface selber erbt diese Grundfunktionen, aber woher soll die Klasse diese denn kennen? TInterfacedObjekt oder TComponent als Vorfahre und man könnte diese erben, aber TThread/TObject kennt das eben nicht. |
AW: Klasse von TTHread ableiten und Interface implementieren, Objekt erstellen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz