|
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.342 Beiträge Delphi 12 Athens |
#1
So, da Einige mit den Interfaces als Callback nicht klar kommen (es ihnen zu umständlich ist),
mal eine Frage, was man nun am Besten machen könnte.
---------- So ist es aktuell
Delphi-Quellcode:
Dieses nun mit einer zusätzlichen EventMethode überladen
type
// das war Einigen zu schwer verständlich zu verstehen {IDECProgress = interface procedure Progress(const Min, Max, Pos: Int64); end;} // aber umbenannt und mit Kommentar ist es nicht wirklich besser geworden IDECProgress = interface /// <summary>... procedure OnProgress(const Min, Max, Pos: Int64); end; IDECHash = interface ... /// <summary>... procedure CalcStream(const Stream: TStream; Size: Int64; var HashResult: TBytes; const OnProgress: IDECProgress = nil); ... end; procedure TMyClass.OnProgress(const Min, Max, Pos: Int64); begin ProgressBar.Min := Min; // 0; ProgressBar.Max := Max; // 100; ProgressBar.Position := Pos; // (Pos - Min) * 100 div (Max - Min); end; und weiter zusätzlich noch ein "optimaleres" Interface. Es gibt es an sehr vielen Stellen nun die einbindenen Methoden somit unschön doppelt/dreifach, wenn man das Alte aus Kompatibilitätsgründen beibehalten möchte, außerdem hat ein Interface auch seine Vorteile.
Delphi-Quellcode:
Vererbung würde das Ausmaß minimieren, aber eine Vererbung ist hier nicht "sinnvoll" möglich
// siehe https://github.com/geheimniswelten/DelphiEncryptionCompendium/compare/development...geheimniswelten:develop/IDECProgress
// funktioniert, aber an vielen Stellen "unschön" mehrfache Implementation, für jeden Callback-Type {$IFDEF FPC} // ich weiß noch nicht ob/wie das mit den Anonymen im Lazarus/FPC geht TDECProgress = procedure(Sender: TObject; const Min, Max, Pos: Int64) of object; {$ELSE} TDECProgress = reference to procedure(Sender: TObject; const Min, Max, Pos: Int64); {$ENDIF} IDECProgress = interface procedure OnProgress(const Min, Max, Pos: Int64); end; IDECProgress2 = interface procedure OnProgressStart(const Min, Max: Int64); procedure OnProgress(const Pos: Int64 {; Percent: Single}); procedure OnProgressStop(const Pos: Int64 {; Percent: Single}); procedure OnProgressError(const Pos: Int64 {; Percent: Single}; const ErrorText: string); end; IDECHash = Interface ... /// <summary>... procedure CalcStream(const Stream: TStream; Size: Int64; var HashResult: TBytes; const OnProgress: IDECProgress2 = nil); overload; procedure CalcStream(const Stream: TStream; Size: Int64; var HashResult: TBytes; const OnProgress: IDECProgress); overload; procedure CalcStream(const Stream: TStream; Size: Int64; var HashResult: TBytes; const OnProgress: TDECProgress); overload; ... end; procedure TMyClass.OnProgressStart(const Min, Max: Int64); begin ProgressBar.Min := Min; ProgressBar.Max := Max; ProgressBar.State := pbsNormal; ProgressBar.Position := 0; StatusLabel.Visible := False; end; procedure TMyClass.OnProgress(const Pos: Int64); begin ProgressBar.Position := Pos; end; procedure TMyClass.OnProgressStop(const Pos: Int64); begin ProgressBar.Position := Pos; ProgressBar.State := pbsPaused; end; procedure TMyClass.OnProgressError(const Pos: Int64; const ErrorText: string); begin ProgressBar.Position := Pos; ProgressBar.State := pbsError; StatusLabel.Caption := ErrorText; StatusLabel.Visible := True; end; und an vielen Stellen ist es weiterhin doppelt (Methode+Interface), auch wenn beide Interfaces nun im selben Parameter-Vorfahren übergeben werden könnten.
Delphi-Quellcode:
Die Verwebung zu verschieben wird bestimmt auch niemand verstehen,
// ist keine Lösung
type IDECProgress = interface procedure OnProgress(const Min, Max, Pos: Int64); end; IDECProgress2 = interface(IDECProgress) {weiterhin ist das das alte OnProgress vorhanden procedure OnProgress(const Min, Max, Pos: Int64); } procedure OnProgressStart(const Min, Max: Int64); procedure OnProgress(const Pos: Int64 {; Percent: Single}); overload; procedure OnProgressStop(const Pos: Int64 {; Percent: Single}); procedure OnProgressError(const Pos: Int64 {; Percent: Single}; const ErrorText: string); end; also mit einem IDECProgressBase oder gar direkt IInterface als Parameter. Und ins letzte Interface passen die Methoden des Originals nicht rein, bzw. ich würde den doppelten OnProgress-Aufruf unschön finden.
Delphi-Quellcode:
Statt der vielen Überladungen könnte man auch nur das größte Interface (IDECProgress2) implementieren
// unverständliche mögliche Lösung
type IDECProgressBase = interface // ohne was drin end; IDECProgress = interface(IDECProgressBase) procedure OnProgress(const Min, Max, Pos: Int64); end; IDECProgress2 = interface(IDECProgressBase) {weiterhin ist das das alte OnProgress vorhanden procedure OnProgress(const Min, Max, Pos: Int64); } procedure OnProgressStart(const Min, Max: Int64); procedure OnProgress(const Pos: Int64 {; Percent: Single}); overload; procedure OnProgressStop(const Pos: Int64 {; Percent: Single}); procedure OnProgressError(const Pos: Int64 {; Percent: Single}; const ErrorText: string); end; und einen "manuellen" Wapper bauen, aber das versteht scheinbar auch niemand, bzw. es ist zu umständlich. ![]() Allerdings ist das von den "möglichen" Implementierung her eigentlich die schönste/schlankeste Variante, auch wenn man bei Übergabe einer Callback-Methode, oder des kleinen Interfaces, einen manuellen Cast einfügen muß.
Delphi-Quellcode:
Als Record-Helper mit Implicit-Class-Operator an dem Interface,
// funktioniert und kompakt (aber findet bzw. versteht vielleicht niemand)
type TDECProgressWrapper = class(TInterfacedObject, IDECProgress2) private ... public class function Create(Sender: TObject; Intf: IDECProgress): IDECProgress2; overload; class function Create(Sender: TObject; Proc: TDECProgress): IDECProgress2; overload; end; Hash := DECHash.CalcStream(Stream, Size, TDECProgressWrapper.Create(OnProgressMethodOrIDECProgress)); das funktioniert leider nicht. ![]()
Delphi-Quellcode:
Aber geil wäre es schon, wenn die Überladungen nur an einer Stelle liegen würden, wie auch beim Wrapper,
// compiliert leider (noch) nicht
type // [dcc32 Fehler] E2474 Record-Typ erforderlich TDECProgressHelper = record helper for IDECProgress2 class operator Implicit(Value: IDECProgress): IDECProgress2; class operator Implicit(Value: TDECProgress): IDECProgress2; end; // [dcc32 Fehler] E2021 Klassentyp erwartet TDECProgressHelper = class helper for IDesignerHook class operator Implicit(Value: IDECProgress): IDECProgress2; class operator Implicit(Value: TDECProgress): IDECProgress2; end; // aber per se kann man scheinbar doch Casts nachträglich anhängen (der Compiler meckert nicht) TIntegerHelper = record helper for Integer class operator Implicit(Value: Byte): Integer; end; TPointHelper = record helper for TPoint class operator Implicit(Value: TRect): TPoint; end; anstatt überall bei jeder Verwendung als overload einbauen zu müssen. Umsetzung siehe ![]() ----- Falls noch jemand andere Lösungen kennt ... bitte immer her damit. Ansonsten fällt mir nur noch eine radikale "übersichtliche" Lösunge ein, also das Interface komplett zu löschen und durch eine Event-Methode zu ersetzen.
Ein Therapeut entspricht 1024 Gigapeut.
Geändert von himitsu (23. Dez 2020 um 02:44 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |