Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Override von Konstanten im Objekt - Alternative? (https://www.delphipraxis.net/194709-override-von-konstanten-im-objekt-alternative.html)

bernau 25. Dez 2017 15:59

Delphi-Version: 10 Berlin

Override von Konstanten im Objekt - Alternative?
 
Ich erkläre mal kurz, was ich möchte, was aber nicht funktioniert

Ich habe ein Basisobjekt (TObjectA). Dort ist eine Konstante definiert. Eine Procedure macht irgendetwas damit.

Ich leite von TObjectA das TObjectB ab. Unterschied ist, daß die Konstante einen anderen Wert hat.

Delphi-Quellcode:
  TObjectA = class
  private
    const
    cTestValue = 'aaa';
  public
    Procedure MachWasMitTestValue;
  end;

  TObjectB = class(TObjectA)
  private
    const
    cTestValue = 'bbb';
  public
  end;
Problem ist natürlich, dass für die "Procedure MachWasMitTestValue" cTestValue immer den Wert 'aaa' besitzt. Auch wenn ich TObjectB instanziere und dort diese Funktion aufrufe.

Die Alternative:

Ich Erzeuge eine virtuelle Funktion im TObjectA und überschreibe diese im TObjectB

Delphi-Quellcode:
Type
  TObjectA = class
  public
    Function testvalue: String; virtual;
    Procedure MachWasMitTestValue;
  end;

  TObjectB = class(TObjectA)
  public
    Function testvalue: String; override;
  end;

  function TObjectA.testvalue: String;
  begin
    Result := 'aaa';
  end;

  function TObjectA.testvalue: String;
  begin
    Result := 'bbb';
  end;
Der Nachteil ist für mich, dass die Werte für TestValue in der Implementation stehen. Ich möchte diese Werte aber direkt in der Deklaration des Objects sehen.

Dann habe ich noch an Properties mit einem Default-Wert gedacht. Damit geht es aber nur mit ordinalen Tpyen. Einen Defaultwert für einen String kann man nicht angeben.

Hat jeman eine Idee, wie ich die Werte in der Deklaration des Objektes festlegen kann und diese trotzdem Virtuell sind, damit die "Procedure MachWasMitTestValue" trotzdem auf die Werte des Kindobjektes zugreifen kann?

Vieleicht Attribute? Kenne ich mich aber nicht mit aus. :-(

Uwe Raabe 25. Dez 2017 16:20

AW: Override von Konstanten im Objekt - Alternative?
 
Kombinier doch einfach beide Ansätze:
Delphi-Quellcode:
Type
  TObjectA = class
  strict private const
    cTestValue = 'aaa';
  public
    Function testvalue: String; virtual;
    Procedure MachWasMitTestValue;
  end;

  TObjectB = class(TObjectA)
  strict private const
    cTestValue = 'bbb';
  public
    Function testvalue: String; override;
  end;

  function TObjectA.testvalue: String;
  begin
    Result := cTestValue;
  end;

  function TObjectB.testvalue: String;
  begin
    Result := cTestValue;
  end;

bernau 25. Dez 2017 16:27

AW: Override von Konstanten im Objekt - Alternative?
 
Da habe ich auch schon dran gedacht.

Wobei das natürlich unnötigen Code erzeugt. Im Beispiel nicht ist es viel. Aber es ist ja nur ein Beispiel. Da sollen zukünftig mehrere abgeleitete Objekte vorkommen und mehrere Konstanten im Objekt. Das macht den Code unübersichtlich.

Aber danke für die Idee!

EdAdvokat 26. Dez 2017 09:48

AW: Override von Konstanten im Objekt - Alternative?
 
warum kann ich die Methode MachwasmitTestvalue auch nach der Freigabe von ObjectA aufrufen?
Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var ObjectA:TObjectA;
begin
  ObjectA := TObjectA.Create;
  try
    lblA.Caption:=ObjectA.testvalue;
    //ObjectA.MachWasMitTestValue;
  finally
    ObjectA.Free;
  end;
  ObjectA.MachWasMitTestValue;
end;
eigentlich gehört sie doch in den try... finaly-Abschnitt, wie auskommentiert dargestellt.

bernau 26. Dez 2017 10:12

AW: Override von Konstanten im Objekt - Alternative?
 
Zitat:

Zitat von EdAdvokat (Beitrag 1389658)
warum kann ich die Methode MachwasmitTestvalue auch nach der Freigabe von ObjectA aufrufen?
Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var ObjectA:TObjectA;
begin
  ObjectA := TObjectA.Create;
  try
    lblA.Caption:=ObjectA.testvalue;
    //ObjectA.MachWasMitTestValue;
  finally
    ObjectA.Free;
  end;
  ObjectA.MachWasMitTestValue;
end;
eigentlich gehört sie doch in den try... finaly-Abschnitt, wie auskommentiert dargestellt.

Ähm. Deinen Post verstehe ich nicht. Ist der Code von dir, oder von einem ggf. gelöschten Post?

Natürlich gehört die Anweisung in den Try...finally Block und muss aufgerufen werden bevor das Objekt wieder freigegeben wird.

Wenn es doch funktioniert, ist es Zufall, weil der Speicherbereich, in dem sich das instanzierte Objekt befunden hatte, noch nicht überschrieben wurde.

EdAdvokat 26. Dez 2017 10:21

AW: Override von Konstanten im Objekt - Alternative?
 
ich habe einfach mit dem Beispiel von Uwe Rabe gespielt und folgenden code vervollständigt:
Delphi-Quellcode:
unit uMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    lblA: TLabel;
    lblB: TLabel;
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    procedure btn1Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Type
  TObjectA = class
  strict private const
    cTestValue = 'aaa';
  public
    Function testvalue: String; virtual;
    Procedure MachWasMitTestValue;
  end;

  TObjectB = class(TObjectA)
  strict private const
    cTestValue = 'bbb';
  public
    Function testvalue: String; override;
  end;

procedure TObjectA.MachWasMitTestValue;
begin
  ShowMessage(testvalue);
end;

function TObjectA.testvalue: String;
  begin
    Result := cTestValue;
  end;

  function TObjectB.testvalue: String;
  begin
    Result := cTestValue;
  end;

procedure TForm1.btn1Click(Sender: TObject);
var ObjectA:TObjectA;
begin
  ObjectA := TObjectA.Create;
  try
    lblA.Caption:=ObjectA.testvalue;
    //ObjectA.MachWasMitTestValue;
  finally
    ObjectA.Free;
  end;
  ObjectA.MachWasMitTestValue;
end;

procedure TForm1.btn2Click(Sender: TObject);
var ObjectB: TObjectB;
begin
  ObjectB:=TObjectB.create;
  try
    lblB.Caption:=ObjectB.testvalue;
    ObjectB.MachWasMitTestValue;
  finally
    ObjectB.free;
  end;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
  close;
end;

end.
Dann habe ich wie geschrieben die Methode MachwasmitTestValue versehentlich nach der Freigabe des ObjectA aufgerufen und es geht. Es geht wie es gehen soll innerhalb des try...finaly-Blocks, aber ach Wunder: auch hinter diesem, aber warum?

Der schöne Günther 26. Dez 2017 10:39

AW: Override von Konstanten im Objekt - Alternative?
 
Zitat:

Zitat von EdAdvokat (Beitrag 1389660)
Es geht wie es gehen soll innerhalb des try...finaly-Blocks, aber ach Wunder: auch hinter diesem, aber warum?

Das ist als würde man fragen warum es immer klappt wenn man bei grün über die Ampel fährt, aber es die letzten beiden male auch keinen Zusammenprall gab als man bei rot drüber fuhr. Das Freigeben eines Objekts löscht seine Daten nicht zwangsläufig aus dem Speicher. Es gibt sie "zur weiteren Verwendung frei". Es kann klappen. Schreibst du deine Prozedur ein wenig anders klappt es vielleicht schon nicht mehr.

Lange Rede, kurzer Sinn: Tu es nicht ;-)

EdAdvokat 26. Dez 2017 10:48

AW: Override von Konstanten im Objekt - Alternative?
 
na gut, Ich fahre also immer ordentlich über die Kreuzung. War ja nur mal so ein Gespiele mit dem Beispiel. Danke

Bernhard Geyer 26. Dez 2017 10:54

AW: Override von Konstanten im Objekt - Alternative?
 
Bau mal in deinem Testprogramm FastMM4 (https://github.com/pleriche/FastMM4) bzw. aktiviere über Compilerdefines die Checks in dem in Delphi (abgespeckten) FastMM4.
Dann wird entsprechend Meckern das du versuchst auf ein freigegebenes Objekt zuzugreifen.

EdAdvokat 26. Dez 2017 12:58

AW: Override von Konstanten im Objekt - Alternative?
 
Hallo Berndhard Geyer; Ich habe mir das Programm FastMM4 heruntergeladen und einen FastMMuseTracker in das Programm aufgenommen.(in der use-Anweisung der dpr wurde als erstes FastMMU aufgeführt):
Delphi-Quellcode:
procedure TForm1.btn4Click(Sender: TObject);
begin
  ShowFastMMUsageTracker;
end;
rufe dann im Programm zunächst den FastMMUUsageTracker auf und dann immer wieder die "falsche Methode"
Delphi-Quellcode:
var ObjectA:TObjectA;
begin
  ObjectA := TObjectA.Create;
  try
    lblA.Caption:=ObjectA.testvalue;
    //ObjectA.MachWasMitTestValue;
  finally
    ObjectA.Free;
  end;
  ObjectA.MachWasMitTestValue;
end;
er läßt mich immer wieder bei "ROT" über die Strasse und nie kommt ein Auto oder ein Polizist. Aus den Anzeigen im Tracker werde ich nicht schlau, ob und wann er mir eine Warnung gibt.
Ich will bitte keine Haupt- und Staatsaktion aus dieser Spielerei machen. Mir ist durchaus klar, dass der Methodenaufruf an dieser Stelle falsch ist, doch warum erhalte ich keine Warnung. Wo könnte ich evtl. eine Änderung dazu einbauen?


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

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