Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Warum kann man Vererbung verhindern (csInheritable)? (https://www.delphipraxis.net/75763-warum-kann-man-vererbung-verhindern-csinheritable.html)

MaBuSE 24. Aug 2006 18:11


Warum kann man Vererbung verhindern (csInheritable)?
 
Hallo,

ich habe mal eine grundsätzliche Frage:

Warum ist es möglich zu verhindern, dass ein Formular abgeleitet werden kann?

Aber nun das Ganze im Detail (am Beisp. von D7):
  • Wir erstellen eine neue Anwendung.
  • Auf das Form1 legen wir einen TButton mit dem onClick Ereignis:
    Delphi-Quellcode:
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Close;
    end;
  • Dann speichern wie das Projekt ab.
  • Im Menüpunkt "Datei -> Neu... -> Weitere..." wechseln wir zu dem "Project1" Tab und wählen das Form1 aus.
  • die IDE zeigt nun ein Formular Form2 an dass vom Typ TForm2 = class(TForm1) ist:
    Delphi-Quellcode:
    unit Unit2;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TForm2 = class(TForm1)
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
      end;

    var
      Form2: TForm2;

    implementation

    {$R *.dfm}

    end.
  • Nun ändern wir die Peoject1.dpr wie folgt ab:
    Delphi-Quellcode:
    program Project1;

    uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1},
      Unit2 in 'Unit2.pas' {Form2};

    {$R *.res}

    begin
      Application.Initialize;
    //  Application.CreateForm(TForm1, Form1); // <- Diese Zeile auskommentieren
      Application.CreateForm(TForm2, Form2);
      Application.Run;
    end.
  • Dann starten wir das Programm.
    Es ist nun ein Form2 zu sehen mit dem Close Button.
So weit so gut.

Mit dieser Technik kann man sich Formulare erstellen, die eine gewisse Basisfunktionalität haben.
Diese können dann in den Anwendungen verwendet werden, ohne das man alles noch mal neu programmieren muß.
Änderungen an den Basisformularen sind auch sofort in allen abgeleiteten Formularen (nach einem Recompile der Programme) verfügbar.

Super !!!
Genau das will ich haben.

Aber:

Wenn man nun eine Komponente auf das TForm1 legt, die in ComponentState kein csInheritable hat, dann kann ich das Formular nicht mehr vererben.

Es gibt 3 Komponenten bei denen das der Fall ist.
  • TActionManager (bzw. TCustomActionManager)
  • TNotebook
  • TTabbedNotebook
Man kann auch sehr leicht eigene Komponenten schreiben, die das Vererben verhindern:
Delphi-Quellcode:
unit VererbungIstDoof;

interface

uses
  SysUtils, Classes;

type
  TVererbungIstDoof = class(TComponent)
  private
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
  published
    { Published-Deklarationen }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Beispiele', [TVererbungIstDoof]);
end;

{ TVererbungIstDoof }

constructor TVererbungIstDoof.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Exclude(FComponentStyle, csInheritable);
end;

end.
Die Hilfe von Delphi 7 schreibt dazu
csInheritable
Abgeleitete Formulartypen können von der Komponente erben. Wenn bei einer der Komponenten eines Formulars das Flag csInheritable nicht gesetzt ist, kann das Formular nicht als Vorfahr für andere Formulare verwendet werden.


Meine Frage ist nun: "Warum kann man das Vererben verhindern?"

bzw. Warum ist das bei den 3 Komponenten der Fall. Sind die etwa nicht "vererbungssicher"?

Weiß das jemand hier im Forum?

Für eine Antwort wäre ich dankbar.

ps: Auch für Vorschläge, wie man trotzdem Formulare mit einem TActionManager vererben kann. ;-)

sakura 24. Aug 2006 18:16

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE
ps: Auch für Vorschläge, wie man trotzdem Formulare mit einem TActionManager vererben kann. ;-)

Zumindest einen Workaround dafür habe ich: DataModule ;)

Den Rest muss ich mir mal durch den Kopf gehen lassen.

...:cat:...

MaBuSE 24. Aug 2006 18:21

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von sakura
Den Rest muss ich mir mal durch den Kopf gehen lassen.

Mir geht das auch schon eine Weile durch den Kopf. (In der DP ist dazu nix zu finden).

Ich dreh mich schon so lange im Kreis, das es mir langsam schwindlig wird :spin2:

DatenModul bringt mir in dem Fall nicht viel. Wäre aber OT das genau zu erklären.

Flocke 24. Aug 2006 18:46

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Nur als Hinweis: es gibt dazu schon eine Anfrage im QC (QC#5853).

MaBuSE 24. Aug 2006 18:49

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von Flocke
Nur als Hinweis: es gibt dazu schon eine Anfrage im QC (QC#5853).

Danke, aber das bringt mich auch nicht wirklich weiter.
Das es von TCustomActionManager explizit entfernt wird wusste ich ja schon.
Aber beruigend zu wissen, dass ich nicht der Einzige bin, der solche Probleme hat.

Der_Unwissende 24. Aug 2006 19:00

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE
ich habe mal eine grundsätzliche Frage:

Warum ist es möglich zu verhindern, dass ein Formular abgeleitet werden kann?

Hi,
ist eigentlich eine wirklich interessante Frage. Hab noch gar nicht drüber nachgedacht, dass Delphi ja auch diese Funktionalität bietet. An sich gibt es ja auch in anderen Sprachen die Möglichkeit eine Klasse nicht erweiterbar zu deklarieren. In Java wäre eine solche Klasse dann mit dem Schlüsselwort final versehen.
Ich weiß nicht warum Delphi in diesen 3 von dir genannten Fällen keine Vererbung zulässt, aber die sehr generelle Motivation sollte hier eigentlich weniger gegeben sein.
So weit ich weiß ist die Motivation eigentlich, dass man Methoden statisch bindet, wenn es keine weiteren Ableitungen gibt. Dies ist in Delphi automatisch bei jeder Methode der Fall, die nicht mit virtual oder dynamic versehen wird. Sollten jetzt also Methoden "mitgeschleppt" werden, die an dieser Stelle noch nicht statisch sind, würde dies so geändert werden. Es entfällt ein Overhead (der zu vernachlässigen sein sollte).
Es ist (imo) häufig mal ärgerlich, wenn man eine Klasse findet und die nicht weiter abgeleitet werden kann. Wie gesagt, ist ein wenig perfomanter (vielleicht stammt es auch aus einer Zeit als es mit der Perfomance noch nicht so weit her war). Heute wird es hauptsächlich für z.B. private Klassen eingesetzt. Hier kann der Kompiler ein wenig mehr optimieren.
An sonnsten ist es vielleicht noch ein gutes Mittel um zu verhindern, dass jmd. ein Komponente die man verkauft einfach ableitet und nach eigenen Bedürfnissen anpasst. Hat jmd. die dcu stünde es ihm sonst (virtuelle Mehtoden vorrausgesetzt) frei dies zu tun, was man natürlich wieder als Leistung verkaufen könnte...

Bin mir allerdings null sicher, ob eine dieser Motivationen auch bei Delphi hinter der Möglichkeit steckt (denke fast eher nicht!).

Gruß Der Unwissende

Jelly 24. Aug 2006 19:01

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Also ich vermute, dass es verschiedene Komponenten gibt, die nur einmal pro Anwendung erlaubt sind, oder genutzt werden sollen (XPManifest, TDatabase usw.).

Grad bei TDatabase darf pro Anwendung nur eine TDatabase pro Datenbank definiert sein. Wenn Du jetzt aber von einer Form erbst, die eine TDatabase implementiert, so hast du zwangsläufig 2 identische Verbindungen.

Dieser Artikel bestätigt auch meinen Verdacht... Mann, bin ich gut :mrgreen:

jbg 24. Aug 2006 19:17

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von Der_Unwissende
Bin mir allerdings null sicher, ob eine dieser Motivationen auch bei Delphi hinter der Möglichkeit steckt (denke fast eher nicht!)

In einem Interview verrät Anders Hejlsberg seine Gründe. (zwar für C#, aber das sollte bei ihm wohl auch bei Delphi gelten)

sakura 24. Aug 2006 19:54

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von jbg
In einem Interview verrät Anders Hejlsberg seine Gründe. (zwar für C#, aber das sollte bei ihm wohl auch bei Delphi gelten)

Da geht es um virtuelle Methoden (default ja vs. nein). Mark geht es aber um was anderes ;)

...:cat:...

jbg 24. Aug 2006 20:10

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von sakura
Mark geht es aber um was anderes

Scheint wohl nicht meine Woche zu sein. :shock:

MaBuSE 25. Aug 2006 10:59

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von Der_Unwissende
Zitat:

Zitat von MaBuSE
ich habe mal eine grundsätzliche Frage:
Warum ist es möglich zu verhindern, dass ein Formular abgeleitet werden kann?

Hi,
ist eigentlich eine wirklich interessante Frage. Hab noch gar nicht drüber nachgedacht, dass Delphi ja auch diese Funktionalität bietet. An sich gibt es ja auch in anderen Sprachen die Möglichkeit eine Klasse nicht erweiterbar zu deklarieren. In Java wäre eine solche Klasse dann mit dem Schlüsselwort final versehen.

Nicht die Komponente ist final, sondern das Form, auf dem so eine Komponente liegt, die diese Eigenschaft hat!

Man packe eine TActionManager auf das Form und das Form ist nicht mehr vererbbar.

Man kann trotzdem noch von TActionManager ableiten.

Zitat:

Zitat von Jelly
Also ich vermute, dass es verschiedene Komponenten gibt, die nur einmal pro Anwendung erlaubt sind, oder genutzt werden sollen (XPManifest, TDatabase usw.).

Grad bei TDatabase darf pro Anwendung nur eine TDatabase pro Datenbank definiert sein. Wenn Du jetzt aber von einer Form erbst, die eine TDatabase implementiert, so hast du zwangsläufig 2 identische Verbindungen.

Dieser Artikel bestätigt auch meinen Verdacht... Mann, bin ich gut :mrgreen:

Im obigen Artikel steht
As a result of form inheritance being introduced in Delphi 2.0, the ComponentStyle property was added to the TComponent class. This property represents a set of style attributes that govern how a component behaves. In particular, the set can hold two possible styles: csInheritable and csCheckPropAvail.

The csInheritable style indicates that the component can be inherited by a descendent form type. For a form to be inheritable (that is, serve as an ancestor to another form), all components on the form must have the csInheritable style set. If any of the components do not include this style, then Delphi will display an error when you attempt to create a new form descendant. The TComponent class sets the csInheritable style by default in its constructor, and for most circumstances, you will not need to change it. However, it may be necessary to remove this style because of how the component is implemented. For example, the TDatabase component class removes this style because there can only be one Database component per database in an application. If this style is not removed, then a form and its ancestor could be used in the same application, thereby causing the Database component on each form to reference the same physical database.


Das ist aber definitiv falsch !!! Man sollte nicht alles glauben, was im Internet steht. ;-)
TDatabase auf ein TForm und ich kann es trotzdem vererben !!!
(Das habe ich gerade in D7 getestet.)
In Delphi 7 haben nur die 3 oben angegebenen Komponenten diese "Ich will nicht, dass mein OwnerForm vererbt wird" Eigenschaft implementiert.
Das kann es also nicht sein.

Auch kann ich mehrere TActionManager auf ein Formular legen.
Das kann es also auch nicht sein.

Selbst das XPManifest kannst du auf beliebige Formulare beliebig oft legen.
Diese Komponente ist nur ein Dummy.
Das Wichtige ist das {$R WindowsXP.res} in der XPMan Unit.
Und das wird nur einmal pro App eingebunden, da die Unit XPMan ja nur einmal in die App gelinkt wird.

Trotzdem Danke für Eure Gedanken ;-)

Hat jemand weitere Ideen (oder gar das Wissen) ?

Hansa 25. Aug 2006 13:00

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zum "Warum ?" kann ich auch nicht viel sagen, aber eventuell einige Hinweise liefern.

Zitat:

Zitat von MaBuSE
..Nun ändern wir die Peoject1.dpr wie folgt ab:
...
Mit dieser Technik kann man sich Formulare erstellen, die eine gewisse Basisfunktionalität haben.
Diese können dann in den Anwendungen verwendet werden, ohne das man alles noch mal neu programmieren muß.
Änderungen an den Basisformularen sind auch sofort in allen abgeleiteten Formularen (nach einem Recompile der Programme) verfügbar.

Super !!!
Genau das will ich haben.

Eine Basisfunktionalität in seine Formulare einzubauen ist der Sinn der Objektablage. Man kann das zwar auch von Hand erledigen (wie hier), aber das ist nicht zu empfehlen wegen zu vieler Quereffekte. Denn : wird es richtig gemacht, so muß man nicht nur die DPR/PAS ändern, sondern auch die DFMs und anderes. Wenn ich ein Formular vererben will, dann sieht das so aus :

Delphi-Quellcode:
inherited frmArtNrAus: TfrmArtNrAus
Erzeuge ich ein leeres Form, dann aber so :

Delphi-Quellcode:
object Form2: TForm2
Das vererbte Formular sieht weiter so aus :

Delphi-Quellcode:
  inherited pnlOben: TPanel
    Height = 161
    object ckbAlpha: TCheckBox
      Left = 296
      Top = 120
      Width = 129
      Height = 17
      Caption = 'alphabetisch sortieren'
      TabOrder = 1
    end
    object btnStart: TButton
Das Panel "pnlOben" ist mit allen Eigenschaften vom Vorfahr-Formular geerbt. Die Checkbox darauf wurde erst jetzt mit diesem Formular eingeführt. Vererbe ich es weiter, so stehen in der DFM nur noch die geänderten Sachen drin. Soll nun irgendwo die Vererbung unterbrochen werden, so könnte es eventuell schon genügen ein inherited wegzulassen. Ein Blick in die DFM eines Formulars, das nicht mehr vererbt werden kann sollte das klären. Oder mal dasselbe Form per Objektablage vererben und nicht von Hand. Da sind sicherlich Unterschiede zu bemerken.

MaBuSE 25. Aug 2006 15:02

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von Hansa
Eine Basisfunktionalität in seine Formulare einzubauen ist der Sinn der Objektablage.

Wenn Du die Objektablage verwendest, und beim Einfügen nicht "kopieren" oder "verwenden" sondern "Vererben" anklickst, machst Du genau das selbe wie ich hier im Beispiel.
Deine DFM-Dateien sehen genau so aus.
Sicherlich werden die Basisformulare in die Objektablage kommen, aber wenn dort ein TActionManager enthalten ist, kann man auch nicht vererben!!!
Das ist die selbe Technologie.
Diese verwenden wir ja auch schon einige Jahre ;-)
Ich habe es im Beispiel nur ohne die Objektablage gemacht um es nicht unnötig zu komplizieren.

Zitat:

Zitat von Hansa
Man kann das zwar auch von Hand erledigen (wie hier), aber das ist nicht zu empfehlen wegen zu vieler Quereffekte. Denn : wird es richtig gemacht, so muss man nicht nur die DPR/PAS ändern, sondern auch die DFMs und anderes. Wenn ich ein Formular vererben will, dann sieht das so aus ...

Welche Quereffekte?
Es wird doch die selbe Technologie verwendet.
Die Änderungen an den DFM Dateien macht die Delphi IDE doch von selbst.

Das Kopieren oder Verwenden in der Objektablage umgeht zwar das Problem, aber ich verliere dann auch die Möglichkeiten.

Ich will ein SDI- sowie ein MDI-Basisformular haben, das in allen Applikationen verwendet werden kann.
Änderungen am Basisformular sollen sich direkt auch auf die abgeleiteten Formulare auswirken (beim nächsten kompilieren).
Ich möchte ein MDI Child Basisformular haben, das von allen MDI-Applikationen verwendet wird.
In dem MDI Child sind auch abstrakte Methoden enthalten, die in der Applikation implementiert werden müssen.
z.B. procedure TMDIChild.SaveData;
Wenn im Menü Speichern gedrückt wird, wird automatisch SaveData des MDI Fensters aufgerufen.
Außerdem möchten wir bestimmte Merkmale in den MDI Child Fenstern über Interfaces realisieren, um sie im Framework besser ansprechen zu können.

Das klappt auch soweit sehr gut. Und ist wie gesagt schon seit Jahren hier im Einsatz.

Die Applikation soll nun eine neue Optik bekommen und so werden gerade die Basisformulare angepasst.

ABER es kann z.B. kein TActionManager verwendet werden.
Egal ob mit oder ohne Objektablage.

Zitat:

Zitat von Hansa
Das Panel "pnlOben" ist mit allen Eigenschaften vom Vorfahr-Formular geerbt. Die Checkbox darauf wurde erst jetzt mit diesem Formular eingeführt. Vererbe ich es weiter, so stehen in der DFM nur noch die geänderten Sachen drin. Soll nun irgendwo die Vererbung unterbrochen werden, so könnte es eventuell schon genügen ein inherited wegzulassen. Ein Blick in die DFM eines Formulars, das nicht mehr vererbt werden kann sollte das klären. Oder mal dasselbe Form per Objektablage vererben und nicht von Hand. Da sind sicherlich Unterschiede zu bemerken.

Das ist doch normal bei der Objektorientierten Programmierung.
Du kannst ja auch nicht die Vererbungskette von Objekten trennen.
Wie willst Du das denn machen. Die DFM-Datei ist ja nur eine Resource, die in die Unit mit {$R *.dfm} eingebunden wird.
Die IDE sorgt im Normalfall dafür, das immer das Richtige drinnsteht.

Warum sollte also die Vererbung unterbrochen werden?

Ich versteh Dein Problem nicht.


Aber danke für den Hinweis ;-)


[edit]@all:
ps: bitte in diesem Thread keine Diskussion über den Sinn und Zweck von Interfaces und abstrakten Methoden führen, dafür gibt es schon andere Threads ;-)
[/edit]

MaBuSE 30. Mär 2007 11:37

Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE
bitte in diesem Thread keine Diskussion über den Sinn und Zweck von Interfaces und abstrakten Methoden führen, dafür gibt es schon andere Threads ;-)

Das solte aber nicht bedeuten, das niemand mehr etwas schreibt.

MaBuSE 7. Jun 2010 13:14

AW: Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE (Beitrag 606756)
Zitat:

Zitat von MaBuSE
bitte in diesem Thread keine Diskussion über den Sinn und Zweck von Interfaces und abstrakten Methoden führen, dafür gibt es schon andere Threads ;-)

Das solte aber nicht bedeuten, das niemand mehr etwas schreibt.

Nach 3 Jahren kann man mal einen *PUSH* wagen ;-)

Das Problem ist zwar nicht mehr aktuell, aber eine Antwort würde mich schon interessieren.
:glaskugel:

sgbSoftwareEntwickler 31. Mär 2011 09:49

AW: Re: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE (Beitrag 1026310)
Zitat:

Zitat von MaBuSE (Beitrag 606756)
Zitat:

Zitat von MaBuSE
bitte in diesem Thread keine Diskussion über den Sinn und Zweck von Interfaces und abstrakten Methoden führen, dafür gibt es schon andere Threads ;-)

Das solte aber nicht bedeuten, das niemand mehr etwas schreibt.

Nach 3 Jahren kann man mal einen *PUSH* wagen ;-)

Das Problem ist zwar nicht mehr aktuell, aber eine Antwort würde mich schon interessieren.
:glaskugel:

Dem Kann ich nur zustimmen: Habe bisher weder Gründe noch eine Lösung gefunden. Stehe vor dem selbe Problem mit TActionManager und TRibbon

SirThornberry 31. Mär 2011 13:14

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Kann es sein das all diese Komponenten deprecated sind? Dann würde es Sinn machen. So verhindert man das neue Formulare auf veralteten Komponenten aufbauen und zwingt somit den Programmierer auf andere Komponenten auszuweichen.

sgbSoftwareEntwickler 31. Mär 2011 13:25

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von SirThornberry (Beitrag 1092211)
Kann es sein das all diese Komponenten depricated sind? Dann würde es Sinn machen. So verhindert man das neue Formulare auf veralteten Komponenten aufbauen und zwingt somit den Programmierer auf andere Komponenten auszuweichen.

Leider muss ich eine zugeben, dass ich deprecated und seine anwendung nicht kenne.

Ich habe Vorhin mal etwas ausprobiert:

Ich habe mir eine eigene Klasse TMeinRibbon von TRibbon abgeleitet und mir daraus eine komponente gebaut:

Code:
unit MeinRibbon;

interface

uses
  Ribbon, Classes, ActnMan;

type
  TMeinRibbon = class(TRibbon)
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

procedure Register;
begin
  RegisterComponents('Test', [TMeinRibbon]);
end;


{ TMeinRibbon }

constructor TMeinRibbon.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FComponentStyle := FComponentStyle + [csInheritable];
end;
Danach habe ich ein Formular erstellt und MeinRibbon1 darauf gesetzt.

Wenn ich das Ganze per Delphi vererbe (Neu -> Vererbare Elemente ...) haut es mir meine komplette konfiguration von MeinRibbon1 zusammen.
Wenn ich es per Hand vererbe (Neu -> Formular ... TForm1 = class(TMeinGrundFormular) <- per Hand im Quellcode), funktioniert soweit alles, aber ich sehe die Ribbonbar nur zur Laufzeit und hab nur Bedingt Zugriff auf die Ribbonbar.

Ich spiele noch mit den Möglichkeiten und versuche das ganze auch für den TActionManager

Falls Ihr eine andere Idee habt, her damit!

Ich werde euch auf dem Laufenden halten.

HeikoAdams 31. Mär 2011 13:45

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von SirThornberry (Beitrag 1092211)
Kann es sein das all diese Komponenten deprecated sind? Dann würde es Sinn machen. So verhindert man das neue Formulare auf veralteten Komponenten aufbauen und zwingt somit den Programmierer auf andere Komponenten auszuweichen.

Denkbar, aber bei TRibbon zumindest eher unwahrscheinlich.

Dafür, einer Komponente die Vererbung zu verbieten, fällt mir nur ein Szenario ein: Als Anbieter von closed source Komponenten könnte man durchaus ein (wirtschaftliches) Interesse daran haben, das Dritte die Komponente nicht erweitern können.

MaBuSE 1. Apr 2011 11:21

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von SirThornberry (Beitrag 1092211)
Kann es sein das all diese Komponenten deprecated sind? Dann würde es Sinn machen. So verhindert man das neue Formulare auf veralteten Komponenten aufbauen und zwingt somit den Programmierer auf andere Komponenten auszuweichen.

Die Komponenten sind nicht "veraltet".
Weder bei Delphi 7 (1. Beitrag) noch bei der aktuellen XE.

Zitat:

Zitat von HeikoAdams (Beitrag 1092217)
Dafür, einer Komponente die Vererbung zu verbieten, fällt mir nur ein Szenario ein: Als Anbieter von closed source Komponenten könnte man durchaus ein (wirtschaftliches) Interesse daran haben, das Dritte die Komponente nicht erweitern können.

Es geht nicht darum die Vererbung einer Komponente zu verbieten.
Welchen Sinn das hat, ist mit klar. (sealed Objects)

Es geht darum, dass eine Komponente verhindert das das Owner/Parent-Formular nicht mehr vererbt werden kann.

Also nochmal:
  • Alle möglichen Komponenten auf Form -> Form kann vererbt werden.
  • Eine der 3 problematischen Komponente (z.B. TActionManager) auf Form -> Form kann nicht mehr vererbt werden.

MaBuSE 4. Jul 2011 17:27

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von HeikoAdams (Beitrag 1092217)
Dafür, einer Komponente die Vererbung zu verbieten, fällt mir nur ein Szenario ein: Als Anbieter von closed source Komponenten könnte man durchaus ein (wirtschaftliches) Interesse daran haben, das Dritte die Komponente nicht erweitern können.

Darum geht es ja gar nicht.
Es wird nicht das Ableiten (Vererben) der Komponenten verhindert. Das ist weiterhin möglich.
Es wird verhindert, das das TForm, auf dem die Komponente liegt vererbt werden kann.

Im 1. Beitrag es es genau erklärt.

MaBuSE 4. Jul 2011 17:40

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE (Beitrag 514331)
Wenn man nun eine Komponente auf das TForm1 legt, die in ComponentState kein csInheritable hat, dann kann ich das Formular nicht mehr vererben.

Es gibt 3 Komponenten bei denen das der Fall ist.
  • TActionManager (bzw. TCustomActionManager)
  • TNotebook
  • TTabbedNotebook

Ich habe gerade mal in Delphi XE nachgeschaut:

Es gibt in Delphi XE 4 Komponenten bei denen das der Fall ist.
  • TActionManager (bzw. TCustomActionManager)
  • TNotebook
  • TTabbedNotebook
  • TRibbon (bzw. TCustomRibbon)

TRibon wurde ja schon von sgbSoftwareEntwickler entdeckt ;-)
Ich wollte nur sichergehen, dass nicht noch mehr Komponenten davon infiziert wurden.

sgbSoftwareEntwickler 5. Jul 2011 08:52

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Das Problem besteht nach wie vor. Ich will die Ribbonbar (mit Actionmanager) in einem bestehenden Grundformular einführen. Ich bin nach wie vor für Ideen offen :)

yörsch 5. Jul 2011 09:27

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
zu TNotebook und Vererbung:
wir nutzen TNotebook intensive! und vermeiden rein aus praktischen Gründen eine Vererbung eines solchen Fensters.

Mann stelle sich vor es gibt ein Fenster mit einem TNotebook auf dem sind 10 Pages.
Insgesamt sind dort Hunderte von Controls drauf. Wenn ich jetzt im Basis Fenster ein
paar Veränderungen mache, hab ich in den abgeleiteten Fenster meine mühe alles wieder
glatt zu ziehen damit alles wieder gut funktioniert...

Schon besser sind Frames die ich dann auf die Seiten des TNotebook plaziere.
---

Und, wenn ich in großen Teams arbeite will ich verhindern das nicht jede Nase ungefragt wichtige, komplizierte Klasse vererbt...

sgbSoftwareEntwickler 5. Jul 2011 09:56

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Aus der Delphi Hilfe:

Zitat:

Zitat von DelphiHilfe
TNotebook wird aus Gründen der Abwärtskompatibilität bereitgestellt. In neuen Anwendungen sollte TPageControl verwendet werden.
...
TTabbedNotebook dient der Rückwärtskompatibilität. In neuen Anwendungen sollte TPageControl verwendet werden.

Das csInheritable Problem kann man ja bei TNotebook und TTabbedNotebook mehr oder weniger leicht umgehen. Natürlich sollte man vor der Umsetzung Nutzen und Aufwand gegeneinander aufwiegen.

Zitat:

Zitat von yörsch (Beitrag 1109991)
zu TNotebook und Vererbung:
...
Mann stelle sich vor es gibt ein Fenster mit einem TNotebook auf dem sind 10 Pages.
Insgesamt sind dort Hunderte von Controls drauf. Wenn ich jetzt im Basis Fenster ein
paar Veränderungen mache, hab ich in den abgeleiteten Fenster meine mühe alles wieder
glatt zu ziehen damit alles wieder gut funktioniert...

Dann hast du meiner Meinung nach den Sinn eines Grundformulares nicht verstanden. Und was hindert Dich daran, deine Frames auf das Grundformular zu setzten? Wenn du sauberes Design hast, solltest du nie Anzeigeprobleme bekommen. Ich zum Beispiel nutze ein Navigationsframe auf das alle anderen Frames kommen. ist für kleine Anwendungen zwar Aufwendig, dafür umso angenehmer wenn man viele Menüpunkte oder Tabs abbilden möchte. Und das Navigationsframe platziere ich auf mein (abgeleitetes) Grundformular. Das abgeleitete Grundformular fasse ich nach Möglichkeit gar nicht an. Höchstens um Menüpunkte ein / auszublenden.


Zitat:

Zitat von yörsch (Beitrag 1109991)
Und, wenn ich in großen Teams arbeite will ich verhindern das nicht jede Nase ungefragt wichtige, komplizierte Klasse vererbt...

Nochmal, hier geht es nicht um sealed Klassen, sondern Komponenten die das Vererben des Parentformulars verhindern.
Und gerade wenn du in großen Teams arbeitest, ist doch ein Grundformular hilfreich, da jeder mit der selben Basis arbeitet / arbeiten muss und somit CorpIdent Geschichten und wichtige (geänderte, neue und/oder entfernte) Funktionalitäten sofort in allen vom Grundformular vererbten Projekten nach der nächsten Kompilierung greifen.

Elvis 7. Jul 2011 09:06

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Das hat eigentlich nix mit Vererbung zu tun. Denn dafür wäre die Sprache zuständig (Delphi hat IMO mitttlerweile abstrakte Klassen?).
Das Problem ist diese grauenvolle Art, in der IDE und Designer einem globale Variablen und unflexibel geteilte Referenzen aufzwingen.
Wenn du ein Form mit einem ActionManager 2-mal instanzierst, bekommst du auch die Actions 2-mal.
Innerhalb des Forms wird er das wohl noch richtig hinkriegen, nutzt du Actions außerhalb dieser Form fangen die Probleme natürlich an.
Ein anderer Grund kann sein, dass sie wohl Probleme haben, so komplexe Strukturen auch in Ableitungen noch reproduzierbar richtig aufzubauen. Wenn du vom Form ableitest und Action entfernst, hinzufügst, bestehende mit andere Handlern versiehst etc.
Vllt kommt dann ein Frankenstein-ActionManager raus, der nix Halbes und nix Ganzes ist.

Man kann halt nur soviel mit einem so einfach gestrickten RAD-Designer von 1995 anstellen, bevor man für 1m Weg 10m Umweg gehen muss.

MaBuSE 7. Jul 2011 11:15

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von Elvis (Beitrag 1110474)
Wenn du ein Form mit einem ActionManager 2-mal instanzierst, bekommst du auch die Actions 2-mal. Innerhalb des Forms wird er das wohl noch richtig hinkriegen, nutzt du Actions außerhalb dieser Form fangen die Probleme natürlich an.

Das ist ein anderes Problem.
Es ist ja durchaus möglich mehrere Instanzen zu verwenden.
Delphi-Quellcode:
...
var
  a, b, c: TMyActionForm;
begin
  a := TMyActionForm.Create(Self);
  b := TMyActionForm.Create(Self);
  c := TMyActionForm.Create(Self);
  a.Show;
  b.Show;
  c.Show;
...
Die IDE versagt nur die Vererbung:
Delphi-Quellcode:
...
type
  TMyForm = class(TMyActionForm)
...
Man beachte: Nur die IDE verweigert das mit der Fehlermeldung:
Zitat:

Fehler beim Erzeugen von Formular: Vererbung von 'Form2' nicht möglich. Es enthält eine Komponente 'AchtionManager1' ohne Vererbungsmöglichkeit.
Wenn man das *.pas und *.dfm von Hand erstellt (z.B. mit Notepad), geht es durchaus zur Laufzeit.

Zitat:

Zitat von Elvis (Beitrag 1110474)
Ein anderer Grund kann sein, dass sie wohl Probleme haben, so komplexe Strukturen auch in Ableitungen noch reproduzierbar richtig aufzubauen. Wenn du vom Form ableitest und Action entfernst, hinzufügst, bestehende mit andere Handlern versiehst etc.
Vllt kommt dann ein Frankenstein-ActionManager raus, der nix Halbes und nix Ganzes ist.

Warum dann aber auch bei TNotebook, TTabbedNotebook und TRibbon (bzw. TCustomRibbon)?
Ein TNotebook ist nun mal nicht sooo komplex.
Und viel interesannter ist die Frage, warum eine TActionList, die auch Actions beinhaltet, erlaubt ist.

Zitat:

Zitat von Elvis (Beitrag 1110474)
Man kann halt nur soviel mit einem so einfach gestrickten RAD-Designer von 1995 anstellen, bevor man für 1m Weg 10m Umweg gehen muss.

Das wird der Grund sein :stupid:

Aber ich sehe die Frage noch nicht als beantwortet :)

sgbSoftwareEntwickler 7. Jul 2011 16:50

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von MaBuSE (Beitrag 1110504)
Aber ich sehe die Frage noch nicht als beantwortet :)

Sehe ich genau so ^^

Hab gerade folgendes probiert:

Ich habe eine Form erstellt, und einen Actionmanager darauf Platziert. Diesen ActionManager habe ich dann als Property dieser Form zur Verfügung gestellt.

Danach habe ich auf meinem Hauptformular eine Komponente (TActionMainMenuBar) gesetzt und diese dann mit dem Actionmanager vom anderen Formular verknüpft.

Die Idee dahinter: Ich muss die form, die den Actionmanager enthält nicht vererben, kann aber das Formular wo es verknüpft ist vererben.

Leider bin ich an dem Versuch gescheitert, Actions von diesem Actionmanager in mein TActionMainMenuBar einzufügen. Hat jemand ne Idee ob und wie das geht?

Den Code findet Ihr im Anhang

MaBuSE 7. Jul 2011 17:32

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von sgbSoftwareEntwickler (Beitrag 1110639)
Die Idee dahinter: Ich muss die form, die den Actionmanager enthält nicht vererben, kann aber das Formular wo es verknüpft ist vererben.
Leider bin ich an dem Versuch gescheitert, Actions von diesem Actionmanager in mein TActionMainMenuBar einzufügen. Hat jemand ne Idee ob und wie das geht?

Du kannst den ActionManager auf ein TForm oder TDataModule legen und quasi einfach verwenden.
Interesanterweise muß noch nicht mal die uses-Anweisung angepasst werden (kein uses Unit2 in der Unit1).
(Beispiel im Anhang)

Um die Menüs zu verknüpfen muß nur der ActionManager auf dem DataModule doppeltgeklickt werden.
Das Fenster ist nicht modal (also Show statt ShowModal) damit kannst Du dann auf das Formular wechseln, in dem Deine Action Toolbars sind und loslegen.
Anmerkung: TActionToolbars müssen von Hand auf das Form gelegt werden, da beim Anlegen aus dem TActionManager versucht würde, die Toolbar in das DataModul zu erzeugen.

Wenn das Dein Problem lösen sollte ;-)

MaBuSE 7. Jul 2011 17:39

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Versucht mal einen TActionManager auf einen TFrame zu legen :twisted:

sgbSoftwareEntwickler 8. Jul 2011 08:51

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE (Beitrag 1110650)
Um die Menüs zu verknüpfen muß nur der ActionManager auf dem DataModule doppeltgeklickt werden.
Das Fenster ist nicht modal (also Show statt ShowModal) damit kannst Du dann auf das Formular wechseln, in dem Deine Action Toolbars sind und loslegen.
Anmerkung: TActionToolbars müssen von Hand auf das Form gelegt werden, da beim Anlegen aus dem TActionManager versucht würde, die Toolbar in das DataModul zu erzeugen.

Wenn das Dein Problem lösen sollte ;-)

Jo, danke. Da hat man eine passable Idee und scheitert an seiner eigenen Blindheit. Das dass Fenster modal ist... darauf wäre ich gar nicht gekommen xD

Zitat:

Zitat von MaBuSE (Beitrag 1110651)
Versucht mal einen TActionManager auf einen TFrame zu legen :twisted:

Der war gut :thumb:

MaBuSE 3. Sep 2012 14:59

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Und wieder ist ein Jahr vergangen und immer noch keine Antwort in Sicht :?

himitsu 3. Sep 2012 15:46

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Hab zwar keine Antwort auf die Frage, also nach dem Warum und so.

Was ich sagen kann, daß auch noch die Ribbons davon betroffen sind, aber die nutzt ja eh Keiner.

Und die Prüfung auf dieses Vererbungszeugs scheint direkt in der Delphi-IDE eingebaut zu sein, so daß man daran auch nicht so leicht was ändern kann.

Was aber eventuell ginge,
Delphi-Quellcode:
type
  TActionManager2 = class(TActionManager)
  public
    constructor Create(AOwner: TComponent); override;
  end;

constructor TActionManager2.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FComponentStyle := FComponentStyle + [csInheritable];
end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TActionManager2]);
end;

Rainer Wolff 15. Nov 2024 16:03

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von MaBuSE (Beitrag 1181265)
Und wieder ist ein Jahr vergangen und immer noch keine Antwort in Sicht :?

inzwischen sind weitere 12 Jahre vergangen, und ich bin über das selbe Problem gestolpert. Ich benutze eine ComPort Library, die etwa ebenso alt ist.
http://comport.sf.net/

Da ist dieses Flag csInheritable ebenfalls ausgeblendet und ich suche den Sinn dahinter.

Die Komponente wurde irgendwann im Grundprojekt ausgetauscht, weil die noch ältere Comport-Komponente, die bis dahin im Einsatz war, nicht mehr wollte (an die Gründe kann ich mich nicht mehr entsinnen).

Vom Grundprojekt abgeleitet gibt es aber ebenfalls noch Projekte, die ähnlich sind und Grundformulare erben und ggf. modifizieren.

An eines dieser abgeleiteten Projekte muss ich jetzt drangehen und habe das selbe Problem.

Ich tendiere dazu, die entsprechende Programmzeile der ComPort-Komponente einfach flach zu legen, wollte aber vorher noch dazu recherchieren, ob das Vererbungsverbot einen tieferen Sinn hat.

himitsu 15. Nov 2024 16:25

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Die Komponente nicht auf der Form, sondern erst im OnCreate erstellen, wäre auch noch eine Lösung.

MaBuSE 15. Nov 2024 17:43

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von himitsu (Beitrag 1543152)
Die Komponente nicht auf der Form, sondern erst im OnCreate erstellen, wäre auch noch eine Lösung.

oder man verwendet nicht die IDE,sondern Notepad ;)

Zitat:

Zitat von MaBuSE (Beitrag 1110504)
...
Man beachte: Nur die IDE verweigert das mit der Fehlermeldung:
Zitat:

Fehler beim Erzeugen von Formular: Vererbung von 'Form2' nicht möglich. Es enthält eine Komponente 'AchtionManager1' ohne Vererbungsmöglichkeit.
Wenn man das *.pas und *.dfm von Hand erstellt (z.B. mit Notepad), geht es durchaus zur Laufzeit.
...





Erstaunlich: Ich habe den Thread 2006 erzeugt. Aber es scheint immer noch ab und zu jemanden zu interessieren. :thumb:


Rollo62 16. Nov 2024 12:41

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Ich weiss generell nicht, ob das Vererben von TForm nicht generell ein Ruf nach Ärger und Problemen ist.
Zum Beispiel eine Basisform mit TPanel usw. und dann in der abgeleiteten Form Komponenten in diese werfen.
Theoretisch sollte das kein Problem sein ...
Ich traue dem IDE Designer nur bedingt und der kommt schon bei TFrames im Designer aus dem Ruder, weshalb ich TFrames nur per Runtime nutze.
Warum sollte das bei TForm anders sein?

Ich verstehe die Motivation und wünsche mir das auch, aber per Runtime ist sowas viel sicherer lösbar.

Medium 18. Nov 2024 15:58

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zumindest unter D2007 hatte ich damit bisher keine Probleme. Unser damaliges Hauptprodukt (welches ich noch immer aktiv pflege) basiert quasi komplett auf einer abgeleiteten TForm-Klasse. Dort sind allerdings keine weiteren Komponenten zugefügt, sondern ein Thread, der für jede Instanz im Hintergrund Dinge erledigt (und ein paar weitere nicht-visuelle Properties).
Daher ist die Benutzung vielleicht auch etwas simpler: Einfach nach Erstellen eines neuen Forms im Code-Editor die Klasse von TForm auf TMyForm ändern, und man kann sogar direkt ohne das Projekt neu zu öffnen weiter machen. Hundertfach im Einsatz - also nicht 100x das gleiche Programm, sondern in Summe ca. hundert individuelle Formulare. (Ist für eine Steuerungsvisualisierung ähnlich Siemens WinCC.)

MaBuSE 18. Nov 2024 18:10

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Zitat:

Zitat von himitsu (Beitrag 1181276)
Delphi-Quellcode:
  FComponentStyle := FComponentStyle + [csInheritable];

Wäre so was nicht auch mit einem Class Helper zu lösen?
Dann müsste man "nur" eine weitere Unit einbinden ;)

Wenig elegant, aber ...

Ich komme leider nicht dazu es zu Testen.
Für die, die nicht wissen was ein ClassHelper ist und was man damit machen kann:
hier ein kleines Tutorial von mir ;)
https://www.delphipraxis.net/164041-...ntdataset.html

himitsu 18. Nov 2024 18:22

AW: Warum kann man Vererbung verhindern (csInheritable)?
 
Nee, da es dort ja kein Override gibt.
und somit kennt der DFM-Reader das Create des Helpers nicht.


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