![]() |
Logische Operatoren als Aufzählungstyp
Wir sind mal wieder beim Thema "Rad nicht neu erfinden".
Ich möchte einer Funktion mehrere Werte als Array übergeben und diese sollen logisch verknüpft werden. Die Verknüpfungsart soll als Parameter übergeben werden. Beispiel
Delphi-Quellcode:
Ich kann natürlich loOr oder loAnd usw. selber definieren.
result1 := meineFunktion(loOr,[Value1,Value2,Value3]);
result2 := meineFunktion(loAnd,[Value1,Value2,Value3]);
Delphi-Quellcode:
Aber bei meinem Glück ist dieser Aufzählungstyp schon irgenwo definiert.
type
TLogicalOperators = (loOr, loAnd, loXor, loNOr, loNAnd, loNXor); Jemand eine Ahnung wo das definiert sein könnte? |
AW: Logische Operatoren als Aufzählungstyp
Dein Delphi sollte wissen, wo es schon definiert wurde. Spontan würde ich einen der fraglichen Bezeichner markieren und über Refactor-> Unit suchen die vorherige Deklaration ermitteln. andererseits dürfte es einfacher sein, die Biester umzubenennen.
Sherlock |
AW: Logische Operatoren als Aufzählungstyp
Nicht dass ich wüsste, vermutet hätte ich so etwas in
Delphi-Quellcode:
oder
System.Math
Delphi-Quellcode:
. Aber da finde ich nichts.
System.Types
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Ich werde es dann selber definieren. |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Auch wenn ich nicht glaube, daß es NOr, NAnd und NXor irgendwo im Delphi geben wird,
kann man doch einfach mal in den Delphi-Quellcodes danach suchen lassen?
Delphi-Quellcode:
+ nur ganze Wörter :stupid:
([a-z_]+nor)
|
AW: Logische Operatoren als Aufzählungstyp
Ich denke nicht dass es sowas schon gibt aber ganz ehrlich gesagt würde ich mir für so ein kleines Enum nicht so viele Gedanken oder sogar so einen Thread machen.
Du hast dir jetzt minuten- oder vllt sogar stundenlang (was ich nicht hoffe^^) Gedanken gemacht und einen relativ langen Beitrag geschrieben um herauszufinden ob du dir diesen 1-Zeiler möglicherweise sparen kannst:
Delphi-Quellcode:
:P :wink:
TLogicalOperators = (loOr, loAnd, loXor, loNOr, loNAnd, loNXor);
Selbst wenn du später (durch Zufall) herausfinden solltest dass es sowas schon gibt sollte das duch Refactoring im Zweifelsfall schnell umgestellt sein ;) |
AW: Logische Operatoren als Aufzählungstyp
Wie wäre es mit einem lokalen Typen der Klasse?
|
AW: Logische Operatoren als Aufzählungstyp
Man kann zwei Listen miteinander verknüpfen und -soweit ich mich erinnere- einen Verknüpfungsoperator mit angeben. Ich meine, die heißen 'loAnd' (nur, was in beiden ist) 'loOr' etc. ('lo'=ListOperation). Obwohl, da bin ich mir nicht so sicher, ich kann mich aber an loXor erinnern.
Wieso führst Du überhaupt einen Enum ein? Schreib doch einfach die paar Methoden separat? Oder mach es mit einzelnen Klassen. Dann verzichtest Du auf dein 'case'-Statement, was in einer sauberen Methode ohnehin nichts zu suchen hat (sagen die Puristen). |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
![]() |
AW: Logische Operatoren als Aufzählungstyp
Mavarik, deine Bemerkung ist mir zu minimalistisch. Bitte (ich bin ein einfacher Mann): Subjekt, Prädikat, Objekt. ;-)
Oder willst Du Operatoren für die Arrays einführen? |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Danke erst mal allen zusammen. Frage ist für mich erst mal beantwortet.
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
ein
Delphi-Quellcode:
Kann ich doch auch schreiben als
result2 := meineFunktion(loAnd,[Value1,Value2,Value3]);
Delphi-Quellcode:
Dann muss ich "nur" noch für meinen Value Typen die entsprechende Operator Classe
Result2 := Value1 and Value2 and Value3;
Delphi-Quellcode:
definieren und schon kann ich wieder wunderschönen Clean-Code schreiben...
BitwiseAnd(a: Typ; b: Typ): Ergebnistyp
Mavarik |
AW: Logische Operatoren als Aufzählungstyp
Klar, aber er hat vielleicht ein ganzes Array und möchte das dynamisch machen...
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
|
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Guckstu ![]() |
AW: Logische Operatoren als Aufzählungstyp
Zitat:
Delphi-Quellcode:
Sieht mir nicht Dynamisch aus, sondern wie variable Parameter Anzahl...
result2 := meineFunktion(loAnd,[Value1,Value2,Value3]);
Aber egal DU must ja wissen was Du brauchst... |
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 00:02 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