![]() |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Delphi-Quellcode:
result2 := meineFunktion(loAnd,EinDynArrayWelches200WerteHabenKann);
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Delphi-Quellcode:
Würde ich den Operator nicht in "MeineFunktion" verwenden, würde es ja so aussehen:
Procedure Irgendetwas;
var lOperator:TLogicalOperator; lMeinArray:TDoubleDynArray; begin lOperator:=GibMirDenOperator; FuelleMeinArray(lMeinArray); MeineFunktion(lOperator,lMeinArray); lOperator:=GibMirEinenAnderenOperator; FuelleMeinArrayMitAnderenWerten(lMeinArray); MeineFunktion(lOperator,lMeinArray); end;
Delphi-Quellcode:
Procedure Irgendetwas;
var lOperator:TLogicalOperator; lMeinArray:TDoubleDynArray; begin lOperator:=GibMirDenOperator; FuelleMeinArray(lMeinArray); case loperator of loAnd:MeineFunktionAnd(lMeinArray); loOr:MeineFunktionOr(lMeinArray); end; lOperator:=GibMirEinenAnderenOperator; FuelleMeinArrayMitAnderenWerten(lMeinArray); case loperator of loAnd:MeineFunktionAnd(lMeinArray); loOr:MeineFunktionOr(lMeinArray); end; end; |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Ja. Kurz. 40Min. Andere Sprache (C++).....
Wenn man so etwas in 3-4 Sätzen zusammenfassen könnte, ist das bestimmt um den Überblick zu erhalten besser. Die Details kann man dann ja im Video anschauen. |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Du hast zwar den case in dem aufrufenden Code vermieden, aber nun wird deine Routine, der du die Operation übergibst zu ner Monsterfunktion, die mehrere Operationen kann. Warum nicht 2 verschiedene Funktionen? Nun mag nicht übermorgen jemand mit ner neuen Logischen Operation, die er entdeckt hat, um die Ecke kommen, aber kennt bestimmt jeder case of und 1, 2, 3 sind behandelt und huch, da hat man ja noch Fall 4 vergessen, wird hinzugefügt und muss nun überall wo man mal nen case auf diesen enum oder was gemacht hat, nachgepflegt werden. Und eh man sich versieht, hat man ne zighundert Zeilen Methode, die opBrötchenbacken, opKaffeekochen und opStaubsaugen kann. Also 3 verschiedene Methoden. Und da kommt das Zauberwort Polymorphie ins Spiel, da kann ich mir eine Basisklasse (oder auch ein Interface) bauen, was mir meine Operation (oder auch ![]() Wie man da hin kommt, kann unterschiedlich sein. Ich persönlich find die Kombination von arrays und enums herrlich, da knallts nämlich direkt beim Kompilieren, wenn jemand mal einen neuen Wert hinzugefügt hat und nicht alle cases gefunden und angepasst hat (kennt man ja, case of ... else raise exception.Create('unbehandelter Fall!') end :wall:). Ich blas das Beispiel aber nun auch gar nicht unnötigerweise mit OOP auf sondern bleib mal bei der prozeduralen Programmierung, da lässt sich das Prinzip nämlich auch anwenden:
Delphi-Quellcode:
In der Irgendetwas Prozedur hast du nun überhaupt nix mehr mit dem enum am Hut und sagst einfach nur, ich brauche eine Operation, gib die mir, damit ich sie aufrufen kann. Und das komplette Mapping ist in diesem Fall hardcoded und kann vom Compiler geprüft werden (in Fällen wo das dynamisch ist, würde sich ein Dictionary anbieten, wo man seine strategien registriert).
type
TArrayOperation = procedure(const values: TDoubleDynArray); TLogicalOperator = (loAnd, loOr); procedure AndDings(const values: TDoubleDynArray); begin // ... end; procedure OrDings(const values: TDoubleDynArray); begin // ... end; const ArrayOperations: array[TLogicalOperator] of TArrayOperation = ( AndDings, OrDings ); Procedure Irgendetwas; var MeineFunktion: TArrayOperation; lMeinArray: TDoubleDynArray; begin MeineFunktion := GibMirDieOperation; FuelleMeinArray(lMeinArray); MeineFunktion(lMeinArray); MeineFunktion := GibMirEineAndereOperation; FuelleMeinArrayMitAnderenWerten(lMeinArray); MeineFunktion(lMeinArray); end; Das Beispiel mit der Polymorphie und wie man dadurch auf cases in Klassen verzichten kann, kannst du dir ja dann in Ruhe anschauen (auch wenns Java is :twisted:). |
AW: Logische Operatoren als Aufzählungstyp
Ich wollte mit Klassenfabriken kommen, aber so ist das schön leichtgewichtig.
Eine Class Factory wäre vielleicht ein wenig oversized für die kleine Geschichte, aber als Übung vielleicht nett (Kann kein Delphi mehr, daher bitte kleine Fehler entschuldigen).
Delphi-Quellcode:
Hä? Eben meint der Typ doch, 'case' ist Müll, und dann klatscht er das doch rein? Ja. 'Case' ist sollte vermieden werden, außer in Klassenfabriken (da ist das legitim). Sagen andere Puristen. Wie schön, wenn sich Softwaretechniker so einig sind :lol:
Type
ILogicalArrayCompressor = interface function Execute (array : TSomeArray); end; TAndArrayCompressor = class (ILogicalArrayCompressor) public function Execute (array : TSomeArray); end; TOrArrayCompressor = class (ILogicalArrayCompressor) public function Execute (array : TSomeArray); end; TArrayCompressorFactory = class class function Create (logicalOperator : TLogicalOperator) : ILogicalArrayCompressor; end; class function TArrayCompressorFactory.Create (logicalOperator : TLogicalOperator) : ILogicalArrayCompressor; begin case logicalOperator of laOr : result := TOrArrayCompressor.Create(); laAnd : result := TAndArrayCompressor.Create(); // Add new operators here else raise ArgumentException.Create('Unknown logical Operator'); end; End; --- Function TUserClass.Calculate (logicalOperator : TLogicalOperator; SomeArray : TSomeArray) : Integer; Begin result := TArrayCompressorFactory.Create(logicalOperator).Execute(SomeArray); End; Das Schöne an so einer Methode (oder der von Stevie) ist doch die: Der Anwender hat ein Array und eine Operation (egal welche) und will, das die Arrayelemente entsprechend verknüpft/verdichtet werden. Welche Operationen es gibt, ist im wurscht. Wenn Du das so umsetzt, kannst Du die Anwenderklasse zu machen, d.h. Du musst sie nicht mehr anfassen, bloß weil eine neue logische Operation hinzugekommen ist. Das bedeutet aber auch, das Du keinen Bockmist mit der Klasse (aus Versehen!) machen kannst (weil Du sie noch nicht einmal neu kompilierst). Sie läuft, ist getestet und der Quellcode ist im Tresor. Du erweiterst trotzdem die Mächtigkeit der Klasse. Natürlich musst Du den Code anfassen, wenn ein logischer Operator dazukommt. Aber die Änderungen sind viel simpler und bergen vor allen Dingen nicht die Gefahr, Code in der Nähe aus Versehen zu zerballern oder kaputt zu optimieren (ein beliebtes Hobby). Also ich find das praktisch. |
AW: Logische Operatoren als Aufzählungstyp
Wenn sich die Klassen/Interfaces in der Factory registrieren, kann diese das schön in z.B. einem Dictionary ablegen. Damit entfällt dann auch die Case-Abfrage, es wird einfach im Dictionary nach dem passenden Interface/der Klasse gesucht und bei Fund die entsprechende Instanz zurückgegeben. Dafür müsste es im Forum auch Beispiele geben, ich bin nur gerade zu faul zum Suchen.
|
AW: Logische Operatoren als Aufzählungstyp
@Stevie: Das sieht erst mal sehr interessant aus. Leuchtet mir ein, daß man bei einer Erweiterung des Aufzählungstyp der Compiler eine Fehlermeldung gibt und man nichts vergessen kann. Muss ich mal probieren.
Allerdings kann ich mir vorstellen, daß das Debuggen nicht so schön ist. Bei "GibMirDieOperation" bekomme ich normalerweise den Aufzählungstyp zurück und der wird mir im Debugger angezeigt. Bei der deiner Funktion bekomme ich ja nicht den Namen der Procedure angezeigt sondern den Pointer. Denke ich. @Dejan Vu: Ist wirklich etwas oversized und auch in deinem Fall weis ich nicht, ob es wirklich angenehm zu debuggen ist. Und mit interfaces stehe ich sowiso auf dem Kriegsfuß. Aber egal. Ich schaue es mir mal an. Danke |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Delphi-Quellcode:
Dasselbe würde auch mit einer class procedure funktionieren, sofern die array compressor Klassen stateless sind. Unnötig, die dann zu instanzieren.
TBaseArrayCompressor = class(TInterfacedObject, ILogicalArrayCompressor)
public procedure Execute(arr: TSomeArray); virtual; abstract; end; TBaseArrayCompressorClass = class of TBaseArrayCompressor; TAndArrayCompressor = class(TBaseArrayCompressor) public procedure Execute(arr: TSomeArray); override; end; TOrArrayCompressor = class(TBaseArrayCompressor) public procedure Execute(arr: TSomeArray); override; end; TArrayCompressorFactory = class class function Create(logicalOperator : TLogicalOperator) : ILogicalArrayCompressor; end; class function TArrayCompressorFactory.Create (logicalOperator : TLogicalOperator) : ILogicalArrayCompressor; const CompressorClasses: array[TLogicalOperator] of TBaseArrayCompressorClass = ( TOrArrayCompressor, TAndArrayCompressor); begin Result := CompressorClasses[logicalOperator].Create; end; Zitat:
Delphi-Quellcode:
.
MeineFunktion MyUnit.AndDings
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:35 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 by Thomas Breitkreuz