Autor Beitrag
sunnyandy
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 47



BeitragVerfasst: So 28.10.07 21:57 
Hallo!

Ich möchte in meinem Interface z.B. folgende Methode schreiben:
ausblenden Delphi-Quelltext
1:
procedure Anzeigen (Dokument: IDokument);					


Eine Klasse, die dieses Interface implementiert, besteht z.B. aus:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
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)
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 47



BeitragVerfasst: So 28.10.07 23:20 
Hallo!

Mein Interface sieht so aus:
ausblenden 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.

ausblenden 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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
type
  TFrameExcelDokument = class(TFrame, IDokumentenansicht)

  private

  public
    procedure Anzeigen (Dokument: TExcelDokument)
  end;
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
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)
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: 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; virtualabstract;. 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 47



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Mi 31.10.07 09:51 
In wiefern kannst du das Design noch ändern? Bist du momentan völlig frei?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 31.10.07 10:34 
user profile iconsunnyandy 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.

ausblenden 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.
ausblenden 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:
ausblenden Delphi-Quelltext
1:
FrameWordDokument1.Anzeigen(MyWordDocument);					
Wobei MyWordDocument IDokument implementieren muss.
Der Compiler kann dann nicht erkennen, dass folgendes falsch ist:
ausblenden 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.