Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Zugriff auf Unterklasse absichern (https://www.delphipraxis.net/193451-zugriff-auf-unterklasse-absichern.html)

Blup 2. Aug 2017 10:46

AW: Zugriff auf Unterklasse absichern
 
Destructor Destroy natürlich immer "override". "reintroduce" unterdrückt zwar die Warnung des Compilers wenn "override" vergessen wurde. Das führt aber dazu, das dieser Destructor z.B. beim Aufruf von Free nicht aufgerufen wird.

Ein Beispiel für eine Lösung mit Nullobject:
Delphi-Quellcode:
  TMethode = class
  protected
    class var FNullObject: TMethode;
    class function CreateNullObject: TMethode;
    class function GetNullObject: TMethode;
  public
    class property NullObject: TMethode read GetNullObject;
  private
    FNo: Integer;
    FName: String;
  protected
    procedure SetNo(AValue: Integer); virtual;
    procedure SetName(const AValue: string); virtual;
  public
    constructor Create;
    destructor Destroy; override;
    function IsNullObject: Boolean;
    property No: Integer read FNo write SetNo;
    property Name: String read FName write SetName;
  end;

  TAnalyse = class
  private
    FNo: Integer;
    FName: String;
    FMethode : TMethode;
    function GetMethode: TMethode;
    procedure SetMethode(AValue: TMethode);
  public
    constructor Create;
    destructor Destroy; override;
    property No: Integer read FNo write FNo;
    property Name: String read FName write FName;
    property Methode: TMethode read GetMethode write SetMethode;
  end;

implementation

class function TMethode.CreateNullObject: TMethode;
begin
  Result := TMethode.Create;
end;

class function TMethode.GetNullObject: TMethode;
begin
  if not Assigned(FNullObject) then
    FNullObject := CreateNullObject;

  Result := FNullObject;
end;

procedure TMethode.SetNo(AValue: Integer);
begin
  if IsNullObject then
    Exit;

  FNo := AValue;
end;

procedure TMethode.SetName(const AValue: string);
begin
  if IsNullObject then
    Exit;

  FName := AValue;
end;

function TMethode.IsNullObject: Boolean;
begin
  Result := (Self = FNullObject);
end;

destructor TMethode.Destroy;
begin
  if IsNullObject then
    FNullObject := nil;

  inherited;
end;

function TAnalyse.GetMethode: TMethode;
begin
  if Assigned(FMethode) then
    Result := FMethode
  else
    Result := TMethode.NullObject;
end;

procedure TAnalyse.SetMethode(AValue: TMethode);
begin
  if AValue.IsNullObject then
    FMethode := nil
  else
    FMethode := AValue;
end;

finalization
  TMethode.FNullObject.Free; // oder im class-destructor

end.

Wosi 2. Aug 2017 10:51

AW: Zugriff auf Unterklasse absichern
 
Zitat:

Zitat von norwegen60 (Beitrag 1377884)
Zitat:

Zitat von Der schöne Günther (Beitrag 1377879)
Eine ganz andere Frage:

Delphi-Quellcode:
destructor Destroy; reintroduce;
:shock: :?:

Die wurde hier im Hause auch schon diskutiert. Der, der diese Klassen definiert hat, meint es sei nötig.

Ich wette er liegt falsch.
Destroy wird von TObject.Free aufgerufen und ist virtual. Mit reintroduce wird der Aufruf des neu definierten Destruktors verhindert.

himitsu 2. Aug 2017 11:11

AW: Zugriff auf Unterklasse absichern
 
Und dieser neue Destructor wird ausschlichlich nur dann aufgerufen, wenn die Variable diesen Klassentyp hat, bzw. gecastet wird.

Free und Destroy über Variable/Cast eines Vorfahren ignoriert dieses Destroy dann, was ja eigentlich fast nie gewollt sein dürfte.
Wenn doch, dann benennt diesen neuen Destructor doch bitte anders.


PS: Post #11, da fehlt der Vorfahre beim NullObject.

Ableitung mit böser Prüfung im Vorfahren.
Delphi-Quellcode:
type
  TMethode = class
    ...
    function IsNullObject: Boolean; {virtual;}
  end;

  TMethodeNullObject = class(TMethodeNullObject);

function TMethode.IsNullObject: Boolean;
begin
  Result := Self is TMethodeNullObject;
end;
oder ohne Ableitung
Delphi-Quellcode:
type
  TMethode = class
    ...
    function IsNullObject: Boolean; {virtual;}
  end;

function TMethode.IsNullObject: Boolean;
begin
  Result := Self = FNullObject;
end;

mjustin 2. Aug 2017 11:34

AW: Zugriff auf Unterklasse absichern
 
Zitat:

Zitat von himitsu (Beitrag 1377890)

Ginge statt diesem auch ein Marker-Interface (so kenne ich es in Java)?

Delphi-Quellcode:
type
  TMethode = class
    ...
    function IsNullObject: Boolean; {virtual;}
  end;

  TMethodeNullObject = class(TMethodeNullObject);

function TMethode.IsNullObject: Boolean;
begin
  Result := Self is TMethodeNullObject;
end;
oder ohne Ableitung
Delphi-Quellcode:
type
  TMethode = class
    ...
    function IsNullObject: Boolean; {virtual;}
  end;

function TMethode.IsNullObject: Boolean;
begin
  Result := Self = FNullObject;
end;

Z.B.

Delphi-Quellcode:
type
  INullObject = interface
[GUID]
end;

TMethodeNullObject = class(TMethodeNullObject, INullObject);


und testen dann mit

Supports(FNullObject, INullObject);
Dadurch spart man das Deklarieren klassenspezifischer Nullobjektklassen.

norwegen60 2. Aug 2017 11:44

AW: Zugriff auf Unterklasse absichern
 
Ich denke das
Zitat:

Zitat von Blup (Beitrag 1377886)
function TAnalyse.GetMethode: TMethode;
begin
if Assigned(FAnalyse) then
Result := FAnalyse
else
Result := TAnalyse.NullObject;
end;
[/delphi]

müsste
Delphi-Quellcode:
function TAnalyse.GetMethode: TMethode;
begin
  if Assigned(FMethode) then
    Result := FMethode
  else
    Result := TMethode.NullObject;
end;
heissen.

Ich verstehe allerdings nicht ganz, warum damit der Zugriff
Delphi-Quellcode:
Label1.Caption := Analyse.Methode.Name
funktionieren sollte. Der Lesezugriff auf FName erfolgt ja immer noch direkt, d.h. ohne Getter und darin enthaltener Prüfung auf IsNullObject.

Nachteil ist, dass alle Properties über Set/Get erfolgen müssen. Da erscheint ein Dummy einfacher.

Blup 2. Aug 2017 12:14

AW: Zugriff auf Unterklasse absichern
 
Hab eure Anregungen und Fehlerhinweise berücksichtigt. War aus dem Stehgreif ohne Entwicklungsumgebung, da kann man sich mal vertippen.

@norweger60
Analyse.Methode liefert üer den Getter nun bei FMethode = nil das Nullobjekt zurück. Der Name ist zwar leer, aber das macht ja bei einem Label auch Sinn. Sollte ein Fehler auftreten, der Schreibzugriffe auf Properties des Nullobjekt zur Folge hat, werden diese ignoriert. So wird der Fehler nicht in andere Programmteile verschleppt.

himitsu 2. Aug 2017 12:19

AW: Zugriff auf Unterklasse absichern
 
Zitat:

Zitat von mjustin (Beitrag 1377892)
Delphi-Quellcode:
type
  TMethodeNullObject = class(TMethodeNullObject, INullObject);
Dadurch spart man das Deklarieren klassenspezifischer Nullobjektklassen.

Die Klasse gibt es dennoch, aber so hätte man eine gemeinsame Prüfmethode für mehrere Klassen.

Wenn man alle NullObjekte in einen gemeinsamen Store (Liste) legt, dann könnte man auch sagen "NullObjekt ist das, was in der Liste ist" und braucht dann nur eine Objektklasse.

norwegen60 2. Aug 2017 13:06

AW: Zugriff auf Unterklasse absichern
 
Zitat:

Zitat von Blup (Beitrag 1377899)
@norweger60
Analyse.Methode liefert üer den Getter nun bei FMethode = nil das Nullobjekt zurück. Der Name ist zwar leer, aber das macht ja bei einem Label auch Sinn. Sollte ein Fehler auftreten, der Schreibzugriffe auf Properties des Nullobjekt zur Folge hat, werden diese ignoriert. So wird der Fehler nicht in andere Programmteile verschleppt.

Analyse.Methode liefert ja auch NIL zurück, wenn ich sie gar nicht belegt habe. Und NIL.Name führt dann zur Exception. Oder überseh ich was?

bra 2. Aug 2017 13:32

AW: Zugriff auf Unterklasse absichern
 
Zitat:

Zitat von zagota (Beitrag 1377876)
Der vermutlich auch nicht funktioniert, wenn Analyse.Methode NIL ist.

Stimmt, da bin ich auch schonmal drüber gestolpert :oops:

Zacherl 2. Aug 2017 13:58

AW: Zugriff auf Unterklasse absichern
 
Zitat:

Zitat von zagota (Beitrag 1377876)
Zitat:

Zitat von bra (Beitrag 1377874)
Es gibt bei Delphi die IfThen-Funktion, die ähnlich wie der Elvis-Operator (kannte die Bezeichnung bisher gar nicht) arbeitet.

Delphi-Quellcode:
Label1.Caption := IfThen(Assigned(Analyse.Methode), Analyse.Methode.Name, '');

Ist aber kein wirklich schöner Code.

Der vermutlich auch nicht funktioniert, wenn Analyse.Methode NIL ist.

Zitat:

Zitat von Der schöne Günther (Beitrag 1377877)
Richtig - Er würde ja erst alle Parameter auswerten (und scheitern) bevor er diese komische
Delphi-Quellcode:
IfThen
-Methode überhaupt betreten würde.

Verstehe ich hier etwas falsch und
Delphi-Quellcode:
IfThen
soll nicht den ternären Operator simulieren? Wenn ich richtig liege, würde nämlich nur
Delphi-Quellcode:
Assigned(Analyse.Method)
ausgewertet - was ja vollkommen legitim ist - und dann abhängig vom Ergebnis das erste- oder zweite Argument zurückgegeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:07 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz