Autor |
Beitrag |
sunnyandy
      
Beiträge: 47
|
Verfasst: So 28.10.07 21:57
Hallo!
Ich möchte in meinem Interface z.B. folgende Methode schreiben:
Delphi-Quelltext 1:
| procedure Anzeigen (Dokument: IDokument); |
Eine Klasse, die dieses Interface implementiert, besteht z.B. aus:
Delphi-Quelltext 1:
| procedure Anzeigen (Dokument: TWordDokument); |
Bei dieser Klasse soll Anzeigen nämlich mit einem ganz bestimmten Dokumententyp ausgeführt werden können, trotzdem möchte ich die Methode im Interface für "allgemeine" Dokumententypen haben.
Natürlich meldet der Compiler, dass die Definition der Prozedur nicht mit dem Interface übereinstimmt, obwohl die Klasse TWordDokument IDokument implementiert.
In Java hatte ich das mal mit Generics gelöst, wie kann ich das hier machen?
Bin für jede Hilfe dankbar!
Gruß, Andy
|
|
alias5000
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: So 28.10.07 22:37
Hm, kannst du zu deinem Beispiel evtl. mal eine komplette (Beispiel-)Klassendefinition hinschreiben? Weil, wenn ich dich richtig verstanden habe, dann hast du einen kleinen Denkfehler in deiner Verteilung von Klassen und der Anzeigen-Methode drinnen (die zweite brauchst du ja nicht zwingend...!?)
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
sunnyandy 
      
Beiträge: 47
|
Verfasst: So 28.10.07 23:20
Hallo!
Mein Interface sieht so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| unit InterfaceDokumentenansicht;
interface
uses InterfaceDokument;
type IDokumentenansicht = interface procedure Anzeigen(Dokument: IDokument);
end;
implementation
end. |
Alle Klassen, die dieses Interface implementieren, sollen die Prozedur "Anzeigen" imeplementieren. IDokument soll dabei aber nur eine "Oberklasse" oder ein Interface sein (Ich weiß ja nicht, wie man es in Delphi machen muss). Es soll also möglich sein, ein TWordDokument, oder TExcelDokument zu übergeben, je nachdem was die konkrete Anzeigen-Methode erwartet.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type TFrameWordDokument = class(TFrame, IDokumentenansicht)
private
public procedure Anzeigen (Dokument: TWordDokument) end; |
Wiederum soll eine andere Klasse ein anderen Dokumententyp erwarten können:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type TFrameExcelDokument = class(TFrame, IDokumentenansicht)
private
public procedure Anzeigen (Dokument: TExcelDokument) end; |
|
|
alias5000
      
Beiträge: 2145
WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
|
Verfasst: So 28.10.07 23:29
Hmm, ich kann jetzt auch vollkommen falsch liegen, aber kommst du vielleicht mit overload; weiter?
Ich meine das so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type TFrameWordDokument = class(TFrame, IDokumentenansicht)
private
public procedure Anzeigen (Dokument: TWordDokument); overload; end; |
Das habe ich aber noch nie probiert, glaube ich. Versuchs einfach mal.
Gruß
alias5000
_________________ Programmers never die, they just GOSUB without RETURN
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 30.10.07 23:14
Das schöne an Interfaces ist doch eben, dass alle Klassen, die diese implementieren, eine gemeinsame Funktionalität bereitstellen, unabhängig von ihrer Vererbung. Wenn Du neben den Informationen in IDokument weitere Informationen zum Anzeigen brauchst, die nicht über das Interface abrufbar sind, ist dein Design schlecht.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Di 30.10.07 23:41
Dein procedure Anzeigen (Dokument: TWordDokument) implementiert nicht das allgemeine procedure Anzeigen(Dokument: IDokument); sondern etwas Spezielleres. Eine allgemeine Implementation ist nicht gegeben. Egal wie "gescheit" ein Compiler ist, wird es nicht klappen. Du kannst nicht verhindern, dass jemand einem TFrameWordDokument ein TExcelDokument zum Anzeigen übergibt, wenn es über allgemeine Interfaces geht. Was soll in diesem Fall deiner Meinung nach passieren? Wie BenBE schon sagt, macht das Design so nicht viel Sinn.
Vielleicht sagtst du uns, was die genaue Anwendung ist. Dann können wir versuchen, ein besseres Design vorzuschlagen.
Wieso nicht z.B. TFrameWordDokument von TWordDokument ableiten mit einer zusätzlichen Methode Anzeigen (ohne Parameter)?
Oder eine Abstract Factory in TDokument einbauen, z.B. function CreateFrameDokument: TFrameDokument; virtual; abstract;. In einer abgeleiteten Klasse kreiert die dann ein TFrameDokument, welches eine Methode Anzeigen besitzt (wiederum ohne Parameter). Bspw. kreiert TWordDokument dann in CreateFrameDokument ein TFrameWordDokument, etc.. So passt immer alles zusammen. Ob das auf deinen Fall anwendbar ist, weiss ich aber nicht.
|
|
sunnyandy 
      
Beiträge: 47
|
Verfasst: Mi 31.10.07 08:22
Hallo,
danke für eure Antworten! Ich glaube, ich habe ein schlechtes Beispiel gewählt, es ist auch zu sehr im Projekt verwebt, um das gut erklären zu können.
Ich versuch es, präzise an einem anderen Beispiel zu erklären:
Nehmen wir mal an, ich schreibe ein paar Datenbankklassen, die alle ein paar bestimmte Methoden (Insert(Kunde: TKunde), Update(Kunde:TKunde)) implementieren sollen. Die Datenbankklasse für Kunden erwartet Kundenobjekte, die Klasse für Verträge erwartet, dass man Verträge übergibt.
Und genau diese Methoden will ich in einem Interface zusammmenfassen.
Ich kann im Interface aber nicht "procedure Insert(Kunde:TKunde)" angeben, denn dann müssten alle Klassen in dieser Methode ein TKunde entgegennehmen.
Kann ich im Interface nicht etwas Allgemeines fordern wie "procedure Insert(SpeicherbaresObjekt: TSpeicherbar)", wober TKunde und TVertrag irgendwie davon ableiten oder diese Schnittstelle implementieren?
Oder ist das Design schlecht?
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Mi 31.10.07 09:51
In wiefern kannst du das Design noch ändern? Bist du momentan völlig frei?
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 31.10.07 10:34
sunnyandy hat folgendes geschrieben: | Kann ich im Interface nicht etwas Allgemeines fordern wie "procedure Insert(SpeicherbaresObjekt: TSpeicherbar)", wober TKunde und TVertrag irgendwie davon ableiten oder diese Schnittstelle implementieren? |
Das geht schon, du darfst nur bei der Deklaration bzw. Implementierung der Methode in einer Klasse, die das Interface implementiert, nicht plötzlich etwas spezielleres als Parameter angeben als im Interface.
Du musst die Prozedur schon genauso deklarieren und musst dann in der speziellen Implementierung in einer Klasse ggf. einen TypeCast durchführen. Damit kann der Compiler zwar nicht mehr prüfen, ob tatsächlich der richtige Typ übergeben wird, aber damit muss man dann leben. Bei sauberer Programmierung sollte das aber auch kein Problem darstellen, und für den Fall der Fälle sollte man eine Ausnahmebehandlung einbauen, falls doch ein falscher Typ übergeben wurde, verbunden mit einer Fehlermeldung, die dir als Programmierer sagt, dass an der Stelle doch ein falscher Typ übergeben wurde.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| unit InterfaceDokumentenansicht;
interface
uses InterfaceDokument;
type IDokumentenansicht = interface procedure Anzeigen(Dokument: IDokument);
end;
implementation
end. | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type TFrameWordDokument = class(TFrame, IDokumentenansicht)
private
public procedure Anzeigen (Dokument: IDokument) end; | So geht dann das: Delphi-Quelltext 1:
| FrameWordDokument1.Anzeigen(MyWordDocument); | Wobei MyWordDocument IDokument implementieren muss.
Der Compiler kann dann nicht erkennen, dass folgendes falsch ist: Delphi-Quelltext 1:
| FrameExcelDokument1.Anzeigen(MyWordDocument); | Das geht aber nicht anders, da es ja gerade darum geht, dass allgemeine Funktionalität in allen abgeleiteten Klassen implementiert wird.
--> Insofern frage ich mich zwar schon, was Interfaces hier für einen Sinn machen, aber funktionieren tut es schon.
|
|
|