![]() |
AW: Pattern: Visitor
In diesem Zusammenhang find ich das Decorator Pattern sehr erwähnenswert. Dieses würde ich in bestimmten Fällen vorziehen. Einen Serializer z.B. würde ich (zumindest in neuen Delphi Versionen) niemals als Visitor sondern als Decorator implementieren.
|
AW: Pattern: Visitor
Zitat:
Das gibt's aber nicht. Es gibt lediglich Überladungen mit TClass1 und TClass2 und die muss ich auch entsprechend aufrufen ;) |
AW: Pattern: Visitor
Zitat:
Grüße. |
AW: Pattern: Visitor
Zitat:
Grüße. |
AW: Pattern: Visitor
Zitat:
Overloading kommt doch über die Übersetzungszeit garnicht hinaus. |
AW: Pattern: Visitor
Ich erkenne auch kein Problem.
Die Klassen TClass1 und TClass2 müssen dem Compiler natürlich bekannt sein. Und Self ist ja dann vom Typ TClass1 oder TClass2. M.E. sollte eine solche Vererbung funktionieren. |
AW: Pattern: Visitor
Zitat:
Frage ist warum ein Test den richtigen Type ermitteln kann, aber Self nicht selbst von diesem Type ist???
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TVisitableBase = class; TVisitor = class(TPersistent) public constructor Create; procedure Visit(element: TVisitableBase); virtual; end; TVisitableBase = class(TPersistent) private FCaption: String; protected public constructor Create(caption: String); procedure AcceptVisitor(visitor: TVisitor); virtual; property Caption: String read FCaption write FCaption; end; TVisitableDerived = class(TVisitableBase) private FCount: Integer; public constructor Create(caption: String; Count: Integer); destructor Destroy; override; property Caption; property Count: Integer read FCount write FCount; end; TVisitorDerived = class(TVisitor) public constructor Create; procedure Visit(element: TVisitableDerived); overload; end; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} { TVisitableBase } procedure TVisitableBase.AcceptVisitor(visitor: TVisitor); begin if (Assigned(visitor)) then visitor.Visit(Self); end; constructor TVisitableBase.Create(caption: String); begin inherited Create; FCaption := caption; end; { TVisitor } constructor TVisitor.Create; begin inherited; end; procedure TVisitor.Visit(element: TVisitableBase); begin if (element is TVisitableDerived) then ShowMessage('caption: ' + element.Caption + '; count: ' + IntToStr(TVisitableDerived(element).Count)) else raise Exception.Create('Fehler: Base'); end; { TVisitableDerived } constructor TVisitableDerived.Create(caption: String; Count: Integer); begin inherited Create(caption); FCount := count; end; destructor TVisitableDerived.Destroy; begin inherited; end; { TVisitorDerived } constructor TVisitorDerived.Create; begin inherited Create; end; procedure TVisitorDerived.Visit(element: TVisitableDerived); begin raise Exception.Create('Fehler: Derived'); end; procedure TForm1.Button1Click(Sender: TObject); var visitor: TVisitorDerived; element: TVisitableDerived; begin visitor := TVisitorDerived.Create; element := TVisitableDerived.Create('Test', 100); try element.AcceptVisitor(visitor); finally element.Free; visitor.Free; end; end; end. |
AW: Pattern: Visitor
Darf ich mal kurz was in die Runde werfen?
Runtime <> Compiletime ;) In TVisitableBase.Accept ist der formale Typ von Self: TVisitableBase, also wird die Überladung Visit(TVisitableBase) genommen. In TVisitableDerived wird diese Methode jetzt nur vererbt, ohne dass sich der formale Typ von Self dort ändert, also ändert sich auch nicht, welche Überladung genommen wird. Zur Laufzeit steckt in dieser Variable aber dann natürlich ein TVisitableDerived. Wenn wir Accept in der abgeleiteten Klasse jetzt neu deklarieren, ist der formale Typ von Self dort nun TVisitableDerived, und es wird auch die richtige Überladung genutzt. |
AW: Pattern: Visitor
Oh ja. Ich hatte übersehen, dass overload schon zur Compilezeit ausgewertet wird. :oops:
Dann dürfte aber der Code
Delphi-Quellcode:
nicht kompilieren, da es ja keine überladene procedure Visit für TVisitableBase gibt - oder?
// Unit A
type IVisitor = interface procedure Visit(const x: TClass1); overload; procedure Visit(const x: TClass2); overload; end; TVisitableBase = class procedure AcceptVisitor(const v: IVisitor); end; TClass1 = class(TVisitableBase) // viele Methoden... end; TClass2 = class(TVisitableBase) // viele Methoden... end; procedure TVisitableBase.AcceptVisitor(const v: IVisitor); begin v.Visit(self); end; |
AW: Pattern: Visitor
Feature Request: man bohre das Syntax-Higlighting soweit auf, daß es nicht-compilierenden Code mit der Fehlerstelle markiert...
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:01 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-2025 by Thomas Breitkreuz