Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zugriff auf Public nur wenn Bedingung erfüllt ist (https://www.delphipraxis.net/150963-zugriff-auf-public-nur-wenn-bedingung-erfuellt-ist.html)

stOrM 1. Mai 2010 16:39


Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Hallo,
irgendwie hab ich grad nen Knoten im Kopf.

Ich würde gerne folgendes erreichen, falls irgendwie sauber machbar:

Sagen wir mal es gibt eine Basisklasse:

TUpdateEngine und mehrere weitere Klassen abhängig vom Betriebssystem z.b.

TWin7,
TWinVista,
TWinXP

Die Basisklasse TUpdateEngine soll beim Create prüfen, um welches Zielbetriebssystem es sich handelt.
Wenn das erledigt ist, sollen nur die Funktionen und Proceduren aus dem Publicteil von aussen ansprechbar sein, die auch zum Zielbetriebssystem passen. Diese Functionen und Proceduren möchte ich gerne in die Klassen TWin7 usw. auslagern.

Mir ist nicht klar, wie ich die Klassen aufbauen muss, damit dies möglich ist, sollte es überhaupt möglich sein?
Zu mal ich gerne alles in einer Unit unterbringen würde.

Vielleicht kann mir jemand mal auf die Sprünge helfen...

Viele Grüsse
s!

mkinzler 1. Mai 2010 16:43

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Führe die entsprechenden Eigenschaften erst in den jeweiligen Unterklassen ein.

stOrM 1. Mai 2010 16:46

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Ok,
Aber wie komm ich von der TUpdateEngine nach z.b. TWin7 mit den Functionen für Win7 nach dem ermitteln des Betriebssystems in TUpdateEngine? Das ist mir nicht klar.

himitsu 1. Mai 2010 16:46

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Delphi-Quellcode:
type
  TWin7 = class(TUpdateEngine)
    ...
  end;
  TWinVista = class(TUpdateEngine)
    ...
  end;
  TWinXP = class(TUpdateEngine)
    ...
  end;

function GetEngine(): TUpdateEngine;
begin
  if TheSystem = '7' then
    Result := TWin7.Create
  else if TheSystem = 'Vista' then
    Result := TWinVista.Create
  else if TheSystem = 'XP' then
    Result := TWinXP.Create
  else
    Fehler;
end;
Tja und nun könnte man extern in den Ableger casten, welcher erstellt wurde.
Delphi-Quellcode:
var Engine: TUpdateEngine;

Engine := GetEngine;
Engine.MachWasWelchesÜberallGeht;
if Engine.isWinXP then // oder  if Engine is TWinXP then
  TWinXP(Engine).MachEtwasWelchesNurInWin7Geht;
Ansonsten alles in TUpdateEngine reinmachen und nur die Zugriffe auf die Property/Funktionen intern unterdrücken (eventuell mit Exceptions), welche im aktuellen System nicht verfügbar sind.

stOrM 1. Mai 2010 16:49

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

Ansonsten alles in TUpdateEngine renmachen und nur die Zugriffe auf die Property/Funktionen intern unterdrücken (eventuell mit Exceptions)
Hehe nun ist die Verwirrung perfekt :mrgreen:
Irgendwie nicht mein Tag heute :cry:

mkinzler 1. Mai 2010 16:51

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Das geht z.B. bei Methoden, wenn du die Abfrage in disen machst und beim falschen OS eine Exception auslöst.
Besser ist aber die andere Alternativ, da sie dem Prinzip der OOP folgt

himitsu 1. Mai 2010 16:53

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

Zitat von stOrM
Hehe nun ist die Verwirrung perfekt :mrgreen:

Delphi-Quellcode:
TUpdateEngine = class
  property isWin7: Boolean ...;
  procedure NurFürWin7;
  procedure NurFürWin7oderXP;
end;

procedure TUpdateEngine.NurFürWin7;
begin
  if not isWin7 then
    raise Exception.Create('ist nicht erlaubst');
  ...
end;

procedure TUpdateEngine.NurFürWin7oderXP;
begin
  if not (isWin7 or isWinXP) then
    raise Exception.Create('ist nicht erlaubst');
  ...
end;

stOrM 1. Mai 2010 16:57

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

Zitat von himitsu
Zitat:

Zitat von stOrM
Hehe nun ist die Verwirrung perKfekt :mrgreen:

Delphi-Quellcode:
TUpdateEngine = class
  property isWin7: Boolean ...;
  procedure NurFürWin7;
  procedure NurFürWin7oderXP;
end;

procedure TUpdateEngine.NurFürWin7;
begin
  if not isWin7 then
    raise Exception.Create('ist nicht erlaubst');
  ...
end;

procedure TUpdateEngine.NurFürWin7oderXP;
begin
  if not (isWin7 or isWinXP) then
    raise Exception.Create('ist nicht erlaubst');
  ...
end;

Mein Gott Himi bist du wieder schnell lol hab grad schon roten Kasten bekommen :shock:
Also Cast wäre besser wenn ich das richtig verstehe als die Exceptionmethode?

mkinzler 1. Mai 2010 17:00

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

Also Cast wäre besser wenn ich das richtig verstehe als die Exceptionmethode?
Ja. Weil hier dann immer nur die verfügbaren Methoden sichtbar sind.
Zudem finde ich eine inflationäre Verwendung von Exceptions auch nicht so gut. (Fahrt nach Gehör statt nacht Sicht)

stOrM 1. Mai 2010 17:04

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
[quote="mkinzler"]
Zitat:

Fahrt nach Gehör statt nacht Sicht)
:mrgreen:

Ok da ist was dran hehe, dann lass ich mir mal ne Badewanne mit Kaffee ein und leg mal los!
Vielen Dank euch beiden! :thumb:

SebE 1. Mai 2010 20:04

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Hallo Leute,
auch wenn ich nicht alles genau gelesen habe, häng' ich mich mal mit rein.

Das mit dem Cast ist doch auch nicht DIE Lösung oder?
Mann muss vor jeder Verwendung Testen, was man erzeugt hat!

Wie wär's mit "leeren" Methoden:

Alles in die Bassis-Klasse. Virtuelle Methoden, nicht abstrakt!
Und die abgeleiteten Klassen einfach gezielt überschreiben.

So kann man auch die "falschen" Methoden aufrufen, welche dann halt nichts unternehmen.

himitsu 1. Mai 2010 20:22

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

Zitat von SebE
welche dann halt nichts unternehmen.

Ja toll, die machen einfach so nichts und dein Programm wundert sich dann später warum was fehlt, obwohl es ja angeblich gemacht wurde.
> jedenfalls sieht es ja von außen so aus ... wenn intern nix gemacht wird und es darüber keine Rückmeldung gibt.
Zitat:

Zitat von SebE
auch wenn ich nicht alles genau gelesen habe,

hättest du das gemacht, dann wären die dir Bedenken diesbezüglich aufgefallen
und auch daß dein Vorschlag schon vorgekommen ist (allerdings mit Rückmeldung).

SebE 1. Mai 2010 21:09

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

hättest du das gemacht, dann wären die dir Bedenken diesbezüglich aufgefallen
und auch daß dein Vorschlag schon vorgekommen ist (allerdings mit Rückmeldung).
Tut mir Leid, dass ich anderer Meinung bin.
Auch beim erneuten Lesen, sehe ich meine Lösung NICHT vorgekommen!
Ich sehe die "Bedenken" an anderer Stelle.
OOP bedeutet in meinen Augen vor allem auch Wartbarkeit.

Und die Lösung, dass bei jeder Verwendung überprüft werden müss, um welches Object es sich denn eigentlich handelt, find ich einfach nur schrecklich.

Zitat:

Ja toll, die machen einfach so nichts und dein Programm wundert sich dann später warum was fehlt, obwohl es ja angeblich gemacht wurde.
> jedenfalls sieht es ja von außen so aus ... wenn intern nix gemacht wird und es darüber keine Rückmeldung gibt.
Was interessiert das mein Programm?

"Deine" Lösung:

Delphi-Quellcode:
if System = 'Win7' then
  TWin7(winObject).machWasMitWin7();
Ohne Else-Zweig fehlt hier auch etwas!
Ansonsten kann man den Methoden einen Rückgabewert (bool) verpassen, wenn's sein muss.

Meine Lösung:

Delphi-Quellcode:
winObject.machWas();
Die Zweite hat folgenden Vorteil:
Falls ich nun möchte, dass einige Aktionen nicht nur auf Win7 sondern zusätzlich noch auf WinXP ausgeführt werden sollen, so ändere ich EINE Methode (die von TWinXP) und muss nicht alle Bedingungen suchen.

Von den dazu wegfallenden Prüfungen seh ich hier mal ab.

David Martens 2. Mai 2010 10:29

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Hi,

1. würde ich ein Interface erstellen, in dem alle gemeinsamen Funktionen/Prozeduren/Properties der 3 Betriebssystemklassen definiert werden.

2. Das Gleiche dann für die 3 Klassen separat.

3. Den Interfaces eine GUID verpassen dann kannst du die Supports Funktion benutzen. !Wichtig!

4. Die 3 Klassen dann vom gemeinsamen Interface und dem spezialisierten ableiten, dann müssen die F./P./P. in den 3 Klassen auch vorhanden sein, sonst komiliert er erst garnicht.

5. In den 3 Klassen nicht private/protected verwenden, sondern strict private/strict protected, dann sind diese auch in der Unit private/protected.

So noch ein wenig Code:
Delphi-Quellcode:
  IWindows = interface(IInterface)
    ['{9cd3bd90-e18a-4e4f-a720-93b515181025}'] // von [url]www.guidgenerator.com[/url]
    function Add(sum1, sum2: Integer): Integer; // als Beispiele
    function Sub(sub1, sub2: Integer): Integer;
  end;

  IWin7 = interface(IInterface)
    ['{e71d5c68-08ae-4f7c-8239-fd058c77f7b2}']
    function Mul(mul1, mul2: Integer): Integer;
  end;

  IWinXP = interface(IInterface)
    ['{788e59bc-3f7a-4456-8951-8cce2abf1a71}']
    function Div(div1, div2: Integer): Integer;
  end;

  TUpdateEngine = class(IWindows)
    function Add(sum1, sum2: Integer): Integer;
    function Sub(sub1, sub2: Integer): Integer;
    ...
  end;
  TWin7 = class(TUpdateEngine, IWin7)
    function Mul(mul1, mul2: Integer): Integer;
    ...
  end;
  TWinXP = class(TUpdateEngine, IWinXP)
    function Div(div1, div2: Integer): Integer;
    ...
  end;

procedure ToWas;
var
  Engine : TUpdateEngine; // oder IWindows wenn die Var. nicht inizialisiert werden muß
  I7     : IWin7;
  IXP   : IWinXP;
begin
  Engine := GetEngine;
  Engine.Add();

  if Supports(Engine, IWin7, I7) then
    I7.Mul();

  if Supports(Engine, IWinXP, IXP) then
    IXP.Div();
end;
Mit der Methode bist du wirklich OOP und auch sehr sauber.

SirThornberry 2. Mai 2010 10:52

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Ich finde die Variante mit dem Cast ebenfalls falsch. Denn sobald eine neue Betriebssystemklasse dazu kommt muss man wieder den gesamten Code ändern anstelle einfach nur eine neue Klasse hinzu zufügen.
Richtig wäre die Variante alles in der Basisklasse zu definieren und gegebenfalls eine Funktion mit anzulegen die zurück gibt welche der Funktionen für das entsprechende System verfügbar sind.
Wenn man dann eine neue Klasse hinzufügt muss wenigstens nicht an allen Stellen geändert werden.

Für mich wäre Ziel, das man einfach nur eine neue Klasse hinzufügt und sonst nichts weiter machen muss wenn ein neues System dazu kommt.

sx2008 2. Mai 2010 11:29

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Zitat:

Zitat von stOrM
Die Basisklasse TUpdateEngine soll beim Create prüfen, um welches Zielbetriebssystem es sich handelt.
Wenn das erledigt ist, sollen nur die Funktionen und Proceduren aus dem Publicteil von aussen ansprechbar sein, die auch zum Zielbetriebssystem passen.

Das wäre doch gerade der falsche Weg.
Ziel muss es sein die Unterschiede zwischen den Windows-Versionen quasi "glattzubügeln".
Hierbei kann das Strategie-Designpattern helfen.
Es gibt dann folgende Klassen:
* TWindowsUpdater (Basisklasse der drei folgenden Klassen)
* TWinXP
* TWinVista
* TWin7
* (TWin8)

Dann gibt es noch eine Faktoryklasse:
Delphi-Quellcode:
TWindowsUpdaterFactory=class(TObject)
  class function CreateWindowsUpdaterObj:TWindowsUpdater;
end;
Die Faktoryklasse erzeugt passend zum Betriebssystem ein TWinXP, TWinVista oder TWin7-Objekt.

Zuletzt gibt es noch die Klasse TUpdateEngine.
Diese Klasse bekommt von Aussen ein Objekt der Klasse TWindowsUpdater zugeteilt.
Innerhalb von TUpdateEngine gibt es keine If-Abfragen oder Case-Anweisungen die sich auf das Betriebssystem beziehen.
Sämtlicher Code der irgendwie Betriebssystemabhängig arbeitet ist in die TWindowsUpdater Unterklassen gewandert.

Vergleiche das skizzierte System mal mit dem Konzept der Druckertreiber.
Niemand der bei klarem Verstand ist würde heutzutage für jeden Druckertyp eine Druckroutine schreiben.
Stattdessen gibt es eine Menge von Operationen, die vom jeweiligen Druckertreiber umgesetzt werden.
Die Anwendung spürt so gut wie nichts davon, auf welchem Drucker sie ihre Ausgaben macht.

David Martens 2. Mai 2010 12:13

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Wenn es nur ums "glattzubügeln" geht dann reicht auch ein Interface mit allen public Deklarationen und dann einfach pro Betriebssystem eine Klasse von dem Interface abgeleitet. Dann die betriebssystemspezifische Umsetzung der Funktionen implementieren, die Variable betriebssystemspezifisch erzeugen und mit Supports nur das eine Interface abfragen, oder gleich so benutzen, kann ja kein anderes sein.

ABER, ich glaube darum geht es ihm nicht. Er will ja zusätzliche Funktionen die nur von einem System unterstützt werden auch implementieren. Und dann ist meine Methode die Beste. ;)

mkinzler 2. Mai 2010 12:25

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Bein einfacher Vererbung ist ein Interface aber nicht unbedingt notwendig

stOrM 6. Mai 2010 23:50

Re: Zugriff auf Public nur wenn Bedingung erfüllt ist
 
Erstmal herzlichen Dank, für die ganzen Anregungen von euch!
Nur irgendwie, gehts mir grad so, je mehr Anregungen kommen umso verwirrter werde ich, da es anscheinend zu dem Thema sehr viele unterschiedliche Meinungen gibt (oder anders gesagt, gibt es wohl keine allgemeingültige Regel) wie man sowas am besten gestaltet :shock: :gruebel:

Viele Grüsse
s!


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:27 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