Man kann ja Interfaces über eine Membervariable implementieren lassen was hervorragend funktioniert. Ich würde aber gerne ein property davon publishen und/oder ggf. die Getter/Setter Funktionen des implements Interface direkt dafür verwenden um mir Wraperfunktionen zu ersparen. Geht soetwas?
type
ICommon = Interface(IInterface)
['{6b10544a-ddb0-43de-9612-348f547110da}']
function GetTest() : Boolean;
property Test : Boolean read GetTest;
end;
TTestLabel = class(ICommon)
fCommon : ICommon;
function GetTestWrap() : Boolean; //dont want to need this...
property CommonInterface : ICommon read fCommon implements ICommon;
published
// property Test; // not working...
// property Test : Boolean read GetTest write SetTest default False; // not working
// property Test : Boolean read fCommon.GetTest write fCommon.SetTest default False; // not working
// property Test : Boolean read ICommon.GetTest write ICommon.SetTest default False; // not working
property Test : Boolean read GetTestWrap ; // working but more code..
end;
implementation
function TTestLabel.GetTestWrap() : Boolean; // dont want to write wrappers for each function...
begin
Result:=fCommon.GetTest(); // just wrap interface function...
end;
Zum einen haben Properties (genauso wie Felder/variablen) in interfaces nichts verloren, da diese den Zustand des Objektes betreffen, und Interfaces nur Methoden nach außen definieren sollen (daher auch der Name Schnittstelle), da Schnittstellen immer möglichst klein gehalten werden sollen.
Wenn du es aber dennoch so machen möchtest, warum machst du es nicht einfach so?
Wenn man interfaces über implements property komplett übernimmt/zuweist, dann finde ich, sind auch propertys sinnvoll und sind auch erlaubt und funktionieren auch. Wenn Interfacesfunktionen wie meist selbst implementiert werden dann hast du recht das properties vielleicht unpassender sind.
Wie gesagt bräuchte ich aber eine published property und da man die Sichtbarkeit natürlich über das interface nicht definieren kann würde ich gerne die property druchaus über die Klasse selbst (nochmal) defnieren/publishen, dazu wären die Funktionen des übernommen Interfaces hilfreich bzw. machen die genau das was ich brauche. Meine Frage war ob man die Funktionen des über implements übernommen/zugewiesenen Interface direkt in der property Anweisung der Klasse verwenden kann, oder wie im Beispiel nur mit einer Wrapperfunktion...
In Interfaces stecke ich noch nicht allzu tief drin, aber ihre Systematik kenne ich von anderen Programmiersprachen (Java, C#, VB) her. Von der Logik her stellen sie einen Vertrag dar: Jeder, der ein Interface implementiert ist auch verpflichtet, alle seine Funktionen selbst(!) zu implementieren. Jeder, der eine Klasse über deren Interface benutzt kann daher sicher sein, dass diese Klasse die Funktionalität auch zur Verfügung stellt.
Das Interface selbst stellt - soweit ich es kenne - die Funktionalitäten selbst nicht zur Verfügung, sondern nur deren Methodenrümpfe. Daher kann über eine Property meines Erachtens auch nicht direkt auf die nicht vorhandenen Funktionalitäten des Interfaces zugegriffen werden, sondern nur über die konkrete Implementierung in der jeweiligen Klasse. Natürlich bleibt es einem unbenommen, in einer Klasse eine Membervariable vom Typ Interface anzulegen. Dann muss aber auch (im Konstruktor, spätestens vor Verwendung) diese Variable mit einem konkreten Objekt einer das Interface implementierenden Klasse referenziert werden. Dann kann ich auf diese konkrete Funktionalität zugreifen, auch in einer Property. Ich wüsste nicht, wie das mit den leeren Methodenrümpfen eines Interfaces gehen sollte. Oder ist das in Freepascal völlig anders???
Danke für die Antworten. Ich habe die Implementierungen/create/destory usw nicht ins Beispiel genommen damit es nicht zu lange/verwirrend wird und meine Farge ja eher auf die published property/interface abzielte. Die Sache man ein Interface über eine property in die eigene Interfacesliste der Klasse übernehmen kann ist eine Funktion von FPC. Ich will eine Funktionalität die mehrere Methoden und propertys umfasst und in X Klassen gebraucht wird nicht bei jeder der Klassen (in der Klasse selbst) nochmals 1:1 scrhreiben/kopieren müssen. Dazu erstelle ich eine Klasse die mir das gewünschte interface implementiert und erzeuge diese als property in allen anderen Klassen und übernehme das Interface mit der implements property Klausel....
Anscheinend ist aber etliches unklar darum jetzt ein volles Beipsiel (Klassen wie TTestLabel soll/gibt es dann X mal und brauchen alle die ICommon Interfacemethoden nicht implementieren sondern unterstützen diese automatisch über die implements ICommon):
unit unit2;
interface
uses Classes,Controls;
type
ICommon = Interface(IInterface)
['{6b10544a-ddb0-43de-9612-348f547110da}']
function GetTest() : Boolean;
property Test : Boolean read GetTest;
end;
TTestLabel = class(TControl,ICommon)
public
fCommon : ICommon;
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
function GetTestWrap() : Boolean; //dont want to need this...
// with this line the Interface gets directed to fCommon
// and i dont need to implement the Interface myself
property CommonInterface : ICommon read fCommon implements ICommon;
published
// property Test; // not working...
// property Test : Boolean read GetTest write SetTest default False; // not working
// property Test : Boolean read fCommon.GetTest write fCommon.SetTest default False; // not working
// property Test : Boolean read ICommon.GetTest write ICommon.SetTest default False; // not working
property Test : Boolean read GetTestWrap ; // working but more code..
end;
// This class implements ICommon and will be uses in many other classes like TTestLabel above
// So not all classes have to implement/write the full interface functions....
TCommonImplementer= class(TComponent,ICommon)
function GetTest() : Boolean;
end;
implementation
function TCommonImplementer.GetTest() : Boolean;
begin
Result:=True;
end;
constructor TTestLabel.Create(TheOwner: TComponent);
begin
inherited;
fCommon:=TCommonImplementer.Create(Self);
end;
function TTestLabel.GetTestWrap() : Boolean; // dont want to write wrappers for each function...
begin
Result:=fCommon.GetTest(); // just wrap interface function...
end;
destructor TTestLabel.Destroy;
begin
fCommon:=nil; // fCommon gets freed over (Self) owner on create, but need to
// set this pointer to nil to get internal RefCounter down to prevent
// segfault (mostly on windows)
inherited;
end;
var
TestLabel : TTestLabel;
Test : Boolean;
initialization
TestLabel:=TTestLabel.Create(nil);
Test:=TestLabel.Test; // this calls TTestLabel.GetTestWrap->TCommonImplementer.GetTest
// but should call more directly TCommonImplementer.GetTest
TestLabel.Free;
end.
type
ICommon = Interface(IInterface)
['{6b10544a-ddb0-43de-9612-348f547110da}']
public // kann es sein, daß da nur ein public fehlt?
function GetTest() : Boolean;
property Test : Boolean read GetTest;
end;
Kann es sein, daß da nur ein public fehlt?
Sind die Member ohne Angabe per default protected?