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 Privat deklarierte Klasse ableiten (https://www.delphipraxis.net/194412-privat-deklarierte-klasse-ableiten.html)

Delbor 17. Nov 2017 13:36

Delphi-Version: XE8

Privat deklarierte Klasse ableiten
 
Hi zusammen
Dieser Thread ist im Grunde die Fortsetzung von hier. Für einen neuen Thread hab ich mich entschlossen, weil das Thema unabhängig vom verlinkten Thread interessant sein könnte.
Der da besprochene TPDFiumFrame deklariert ein Klasse TPDFPage in einem private-Abschnitt - es gibt, mir unverständlich, weshalb, 2 davon. TPDFiumFrame legt in einer TList-Instanz ein Handle auf eine TPDFPage-Instanz, bzw auf die da repräsentierte PDF-Seite ab, Diese Liste ist public deklariert, kann also von aussen angesprochen werden.

Tja, mein erster Ansatz war nun, in der Mainform, die mehrere Instanzen dieses TPDFiumFrames nutzt, eine neue Instanz der Klasse TPDFPage zu erstellen. Das ging aber gründlich schief, da in der von TPDFiumFrame benutzten Unit TSynPDF auch eine Klasse TPDFPage deklariert ist, die aber von TPDFDictonary abgeleitet ist.

Nun bin ich auf die Idee gekommen, im Public-Abschnitt von TPDFiumFrame eine neue Klasse TPDFDocumentPage zu erstellen und die von der privaten Klasse TPDFiumFrame.TPDFPage abzuleiten. Dabei soll TPDFDocumentPage keine neuen Member einführen.

Die Deklaration wäre auf dies Weise sehr einfach:
Delphi-Quellcode:
type
TPDFDocumentPage  = class(TPDFiumFrame.TPDFPage)
  private
  public
end;
TPDFiumFrame.TPDFPage zu schreiben, ist mir jetzt gerade eingefallen - sollte im TPDFiumFrame SynPDF im Uses-Teil aufgeführt sein, könnte es Konflikte geben oder sogtar von einer völlig falschen Klasse abgeleitet werden.

Tja, und jetzt kommt mein eigentliches Problem: Irgendwo hab ich mal mitgekriegt, dass in einer abgeleiteten Komponente/Klasse Member ohne explizite Typangabe aufgeführt werden können, weiss aber nicht mehr, woher ich das habe. Hier, bei Delphi-Treff und in der EntwicklerEcke habe ich dazu nichts gefunden. Auch meine klugen Bücher schweigen sich darüber aus.
Daher wollte ich bei Embarcadero nachsehen, aber wies ausschaut, haben die ihren Server geade heute ins Nirwana geschickt.

Weiss jemand mehr?

Gruss
Delbor

TiGü 17. Nov 2017 14:39

AW: Privat deklarierte Klasse ableiten
 
Zitat:

Zitat von Delbor (Beitrag 1386495)
...dass in einer abgeleiteten Komponente/Klasse Member ohne explizite Typangabe aufgeführt werden können...

Darunter kann ich mir nichts vorstellen?!
Was willst du machen?

Delbor 17. Nov 2017 14:57

AW: Privat deklarierte Klasse ableiten
 
Hi TiGü

Na, zum Bleistift statt:

Delphi-Quellcode:
FPoint : TPoint;


nur:

Delphi-Quellcode:
FPoint;


Ich glaube mich zu erinnern, dass dies bei Erhöhen derSichtbarkeit der Fall ist. Aber sicher bin ich mir eben nicht. Und Embarcareo scheint sich immer noch im Nirwana aufzuhalten..

Gruss
Delbor

TBx 17. Nov 2017 15:15

AW: Privat deklarierte Klasse ableiten
 
Das geht nur bei Properties.
Hast Du diese in einer Klasse protected deklariert:
Delphi-Quellcode:
TFoo = class
private
  fInfo: string;
protected
  property info read finfo write finfo;
end;
Willst du nun in der abgeleiteten Klasse Bar info published machen, ist das so möglich:
Delphi-Quellcode:
TBar = class(Too)
published
  property info;
end;
Die Sichtbarkeit von private deklarierten Properties kannst Du aber nicht erhöhen.

Delbor 17. Nov 2017 15:57

AW: Privat deklarierte Klasse ableiten
 
Hi TBx

Vielen Dank!

Gruss
Delbor

Rollo62 18. Nov 2017 07:00

AW: Privat deklarierte Klasse ableiten
 
Das geht dann vieleicht in den Bereich "nasty hack" :-)

Würde ich nur ein extremen Ausnahmefällen machen und gut Unit-Testen und dokumentieren.

Rollo

Delbor 18. Nov 2017 10:21

AW: Privat deklarierte Klasse ableiten
 
Hi Rollo

Da mein Englisch sehr schlecht ist, hab ich mir die Beiträge unter deinem Link mal von Google übersetzen lassen. Inzwischen kommen mit dem Ding ja tatsächlich verständliche und nachvollziehbare Übersetzungen zustande.

Wenn ich das jetzt richtig verstanden habe, besteht das Problem darin:
Sollte sich die Deklarationsstruktur des TPDFiumFrame bei einem Update des Frames ändern und auch nur ein privates Feld dazukommen, verschiebt das die ganzen nachfolgenden Deklarationen nicht nur im Quelltext-Editor nach unten, sondern sie erhalten auch eine neue Speicheradresse.

Ich seh hier allerdings in diesem Fall kein Problem. Denn wenn es mal ein Update des TPDFiumFrames geben sollte und ich dieses einbauen will, muss ich auch meine Klasse neu einfügen und neu compilieren, wodurch sich das Problem 'voon selbst' erledigen sollte.

Meine Deklaration (wobei ich gerade sehe, dass sie Falsch ist - ich beabsichtige nicht, irgendwas zu veränder oder irgendwelche Methoden zu überschreiben. Ich benötige lediglich in meiner Mainform eine Klassenvariable, die mit TPDFiumFrame.TPDFPage kompatibel ist :
Delphi-Quellcode:
  public
    { Déclarations publiques }
    type
      TPDFCustomDocumentPage = class(TPDFPage)
//        Index   : Integer;
//        Handle  : HPDFPage;
//        Top     : Double;
//        Rect    : TRect;
//        Text    : HPDFTextPage;
//        NoText  : Boolean;
//        Visible : Integer;
//        SelStart : Integer;
//        SelStop : Integer;
//        Selection: TArray<TRectD>;
//        destructor Destroy; override;
//        function HasText: Boolean;
//        function CharIndex(x, y, distance: Integer): Integer;
//        function CharCount: Integer;
//        function Select(Start: Integer): Boolean;
//        function SelectTo(Stop: Integer): Boolean;
//        function ClearSelection: Boolean;
//        procedure DrawSelection(DC, BMP: HDC; const Blend: TBlendFunction; const Client: TRect);    
      end;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

Den ganzen hier auskommentierten Teil kann ich weglassen. War wohl schon etwas spät gestern abend...

Gruss
Delbor

TBx 18. Nov 2017 11:01

AW: Privat deklarierte Klasse ableiten
 
Irgendwie komme ich noch nicht so ganz dahinter, was Du eigentlich vorhast.
Willst Du eine private Typdeklaration ableiten, also sowas:
Delphi-Quellcode:
TFoo = class
private
  type
   TMaker = class
     procedure bulb;
  end;
end;
Dann wird sowas nicht funktionieren:
Delphi-Quellcode:
TBar = class(Too)
public
  type
   TMyMaker = class(TMaker)
  end;
end;
Hast Du hingegen sowas:
Delphi-Quellcode:
TFoo = class
private
  TopSecret: Object;
end;
kannst Du Dir über einen class Helper helfen:
Delphi-Quellcode:
TFooHelper = class helper for TFoo
  function getTopSecret: TObject;
end;

function TFooHelper.getTopSecret: TObject;
begin
  Result := self.TopSecret;
end;

Delbor 18. Nov 2017 13:06

AW: Privat deklarierte Klasse ableiten
 
Hi TBx

So auf den ersten Blick fürchte ich, dass das, was ich vorhabe, deinem ersten Beispiel entspricht, zumal unter dem Nastly-Link auch ein Classhelper eingesetzt wird. Daher mal die Deklaration des PDFiumFrames:
Delphi-Quellcode:
 TPDFiumFrame = class(TFrame)
  private
    { Déclarations privées }
    type
      // One point is 1/72 inch (around 0.3528 mm).
      TPointsSize = record
        cx : Double;
        cy : Double;
      end;

      TRectD = record
        Left  : Double;
        Top   : Double;
        Right : Double;
        Bottom : Double;
      end;

      TPDFPage = class
        Index   : Integer;
        Handle  : HPDFPage;
        Top     : Double;
        Rect    : TRect;
        Text    : HPDFTextPage;
        NoText  : Boolean;
        Visible : Integer;
        SelStart : Integer;
        SelStop : Integer;
        Selection: TArray<TRectD>;
        destructor Destroy; override;
        function HasText: Boolean;
        function CharIndex(x, y, distance: Integer): Integer;
        function CharCount: Integer;
        function Select(Start: Integer): Boolean;
        function SelectTo(Stop: Integer): Boolean;
        function ClearSelection: Boolean;
        procedure DrawSelection(DC, BMP: HDC; const Blend: TBlendFunction; const Client: TRect);
      end;

  private
    FDocument : HPDFDocument;
    ......
Und der durch mich erweiterte Teil:
Delphi-Quellcode:
  public
    { Déclarations publiques }
    type
      TPDFCustomDocumentPage = class(TPDFPage) // Die fragliche Klasse.
        private
        public
      end;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Invalidate; override;
    procedure LoadFromMemory(APointer: Pointer; ASize: Integer);
    procedure LoadFromStream(AStream: TStream);
    procedure LoadFromFile(const AFileName: string);
    procedure ClearSelection;
    function PageLevelZoom: Single;
    function PageWidthZoom: Single;
    property Document: HPDFDocument read FDocument;
    property PageIndex: Integer read FPageIndex;
    property PageCount: Integer read FPageCount;
    property Zoom: Single read FZoom write SetZoom;
    property ZoomMode: TZoomMode read FZoomMode write SetZoomMode;

    // Erweitert durch mich
    Property PDFPageList: TList read FPages; // Dieses Property erlaubt mir von aussen (Mainform) den Zugriff auf die Items(PDF-Seiten und deren Abmessungen)
  end;

Und die Mainform deklariert dann eine kompatible Klassenvariable, zum Beispiel nur Lokal, um auf die von PDFium.PDFPageList zurückgegeben PDFSeite, bzw deren Handle, zugreifen zu können:
Delphi-Quellcode:
procedure TSynpdfMain.PDFiumFrame1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
  var SP, FP :TPoint; XF : Integer; PdfPage : TPDFiumFrame.TPDFCustomDocumentPage;
begin
  PdfPage := TPdfPage.Create(Owner);

Mit einem Classhelper würde dies wohl so ausehen:

Delphi-Quellcode:
  public
    { Déclarations publiques }
    type
      TPDFPageHelper = class(TPDFPage)
        private
        public
        function GetPage(Index: Integer) : TPDFPage;
        Property PDFPageList: TList read FPages;
      end;    
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
...
    property Zoom: Single read FZoom write SetZoom;
    property ZoomMode: TZoomMode read FZoomMode write SetZoomMode;
  end;
Wobei dieser Code immer noch im Frame steht. Ausserhalb, also in der Mainform, brauche ich einen kompatiblen Datentyp. Im Falle der Funktion müsste dies eine Klassenvariable (oder eine Instanz?) vom Typ TPDFPage sein. Das ist aber nicht möglich, da in der Unit SynPDF eine Klasse TPDFPage deklariert ist, die aber von TPDFDictionary abgeleitet und somit ganz anders aufgebaut ist.

Gruss
Delbor

TBx 18. Nov 2017 13:37

AW: Privat deklarierte Klasse ableiten
 
Da dir ja offensichtlich der Quelltext vorliegt, warum passt Du die Klasse nicht Deinen Bedürfnissen an?
Die Typdeklaration public machen und eine public Property auf die entsprechende private Variable weisen lassen.

Dann hast du alles, was du für den Zugriff von außen brauchst.
Solche Änderungen kann man über eine Versionsverwaltung gut nachvollziehbar halten. Arbeitest Du mit GIT mit einem geschickten Branching, kannst Du Deine Änderungen in eine neuere Version der Ursprungsquellen über ein Rebase recht einfach wieder einarbeiten.


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