![]() |
class helper
Hallo,
ich setz zum ersten mal einen class helper ein und hab dazu eine Frage ob das zu Problemen kommen kann oder nicht. Ich habe eine ListBox auf der Form liegen und möchte nun die Klasse TListBox in der Unit um eine Variable erweitern. Ich hab nun folgendes stehen:
Delphi-Quellcode:
Es funktioniert - ich habe die Variable nun zur Verfügung bei einer ListBox-Instanz und kann diese auch problemlos nutzen.
type
TListBoxHelper = class helper for TListBox class var aktive_Datei: String; end; TMainForm = class(TForm) {...} Nur kann es so zu Problemen kommen? - oder ist das genau für so was gedacht gewesen? |
AW: class helper
Hallo,
falls Du die Variable für eine Instanz nutzen möchtest, dann solltest Du ein Feld und keine Klassenvariable nutzen. -- Roman Kassebaum |
AW: class helper
Zitat:
ohne class var gehts nicht |
AW: class helper
Interessanter Artikel dazu:
![]() |
AW: class helper
Zitat:
Dort sind im class helper "nur" procedures und functions deklariert - aber keine einfache Variable. Wenn ich die Variable einfach so definiere:
Delphi-Quellcode:
gibts diesen Fehler:
TListBoxHelper = class helper for TListBox
private aktive_Datei: String; end; Zitat:
Delphi-Quellcode:
versteh ich grad etwas falsch?
class var
aktive_Datei: String; end; (dummerweise ist die Delphi-Hilfe nicht wirklich eine Hilfe dabei) |
AW: class helper
Class Helper können keine zusätzlichen Felder für Instanzen bereitstellen! Es sind lediglich Methoden erlaubt.
|
AW: class helper
Zitat:
Delphi-Quellcode:
die einzige Lösung für mein "Problem"?
class var
|
AW: class helper
Allister Christie hatte mal ein nettes Video dazu veröffentlicht:
![]() Im Grunde kann man damit Dinge wie in normalen Funktionen regeln, nur dass der Compiler so tut, als würde die Funktion zur Klasse gehören. Statt
Delphi-Quellcode:
kannst Du
X := GetResult(MyClass);
Delphi-Quellcode:
schreiben.
X := MyClass.GetResult;
Die Funktion GetResult kann aber nur auf öffentliche Eigenschaften der Klasse zugreifen. Man kann der Klasse KEINE Variablen hinzufügen. (Dass class var geht, hätte ich gar nicht gewusst/gedacht.) |
AW: class helper
In dem Fall muss man sich mit einer Cracker-Klasse behelfen, da geht das dann wieder.
Delphi-Quellcode:
uses Windows, SysUtils, {...,} StdCtrls;
type TListbox = class(StdCtrls.TListbox) private FAktive_Datei: string; public property Aktive_Datei: string read FAktive_Datei write FAktive_Datei; end; TDeinForm = class(TForm) DeineListbox: TListbox; //das ist dann die gerade definierte ... end; |
AW: class helper
Zitat:
aber das ist eine andere Diskussion... |
AW: class helper
Zitat:
|
AW: class helper
Hallo,
um noch einmal auf meine erste Antwort zurückzukommen: Es wird eine Variable pro Instanz benötigt. Klassenvariablen können das nicht leisten. Also muss man sich etwas anderes überlegen. Ich persönlich würde wahrscheinlich mit einem Feld arbeiten. Da Klassenhelper das nicht können, würde ich ableiten oder mir das Feld in dem Formular merken. Das kommt auf den konkreten Fall an. -- Roman Kassebaum |
AW: class helper
Zitat:
Ich nutz jetzt DeddyH´s Cracker-Klasse. |
AW: class helper
Ein
Delphi-Quellcode:
oder eine CrackerKlasse haben beide allerdings Nachteile: Die Wirkung ist nicht mehr gesteuert sondern gilt für alle betroffenen Klassen (in diesem Bereich).
class helper
Nehmen wir mal als Beispiel, dass du in einer TListBox eine Datei anzeigen möchtest und eben den Dateinamen dir merken möchtest, dann würde ich folgenden Ansatz bevorzugen:
Delphi-Quellcode:
Nun kann man sehr genau steuern, welche ListBox man damit ansprechen möchte.
unit TextFilePresenter;
interface uses StdCtrls; type TTextFilePresenter = class private FFileName : string; procedure SetFileName(const Value : string); protected procedure Present; virtual; abstract; public property FileName : string read FFileName write SetFileName; end; TTextFilePresenterListBox = class( TTextFilePresenter ) private FListBox : TListBox; procedure SetListBox( const Value : TListBox ); protected procedure Present; override; public property ListBox : TListBox read FListBox write SetListBox; end; implementation uses SysUtils; procedure TTextFilePresenter.SetFileName( const Value : string ); begin FFileName := Value; Present; end; procedure TTextFilePresenterListBox.Present; begin if Assigned( FListBox ) then if FileExists( FileName ) then FListBox.Items.LoadFromFile( FileName ) else FListBox.Clear; end; procedure TTextFilePresenterListBox.SetListBox( const Value : TListBox ); begin FListBox := Value; Present; end; end. Egal in welchem Formular und ohne Nebenwirkungen. |
AW: class helper
Zitat:
Delphi-Quellcode:
,
published
Delphi-Quellcode:
,
public
Delphi-Quellcode:
und
protected
Delphi-Quellcode:
Member der erweiterten Klasse zugreifen. Hatte ich nicht erwartet, kam aber raus, als ich Tests zur Implementierung der class helper in Free Pascal schrieb...
strict protected
Dass class helper jedoch auch
Delphi-Quellcode:
unterstützen war mir entfallen :shock:
class var
Gruß, Sven |
AW: class helper
noch ein Nachtrag; class var geht, weil es keine Instanz-Variable ist. Es wäre genau so, als wenn du eine globale Variable deklarierst.
Class Var ist sogar verfügbar, wenn es keine Instanz gibt. Lediglich der Zugriff erfolgt via <Classname>.Variable statt nur Variable. cheers Ms. |
AW: class helper
Zitat:
Mit einer CrackerKlasse muss man das Objekt ggf. casten je nachdem von welcher Klasse das Objekt instanziiert wurde und wie es weiter verarbeitet werden soll. Streng genommen sind es nicht mehr die gleichen Klassen (auch wenn deren Namen noch gleich sind). |
AW: class helper
Obwohl es vielleicht eher akademischer Natur ist, gefallen mir die Ansaetze hier eher nicht. Wozu gibt es die Vererbung?
Also TmyListbox = class(tlistbox) // erweiterungen einbauen Ggf. Als neue Komponente installieren und verwenden. Cheers mschmidt |
AW: class helper
Zitat:
Meine "Presenter" oder "Adapter" Klasse kann leicht auch auf andere visuelle Komponenten/Frameworks angepasst werden und über eine Factory kann ich diese verbinden. Dadurch kann ich der Factory z.B. ein TMemo, TListBox oder TComboBox (VCL sowie FMX) übergeben und bekomme eine Instanz vom Typ der Basisklasse zurück. Bei dieser Instanz ändere ich die Eigenschaft FileName und fertig ist. Mit deinem Ansatz müsste ich immer die konkrete Ableitung der Komponente ansprechen (ja, auch möglich per RTTI, aber schick ist das nicht). |
AW: class helper
Es wird doch akademisch :-D, ok. In diesem Falle gebe ich dir recht. Jedoch faellt doch das argument, wenn man mehrere funktionalitaeten erweitern moechte. Mehrfachvererbung geht bei D nicht. Imho fange ich dann an, viele adapter zu bauen. Meine persoenliche Meinung ist, strikte Kapselung, sprich; nur die Klasse (visuell oder nicht) selbst kennt seine Funktionalitaeten, fremde Zugriffe erfolgen auf Properties/fkt/proc. Die implementation ist verborgen und physisch auf eine unit beschraenkt. Wird eine neue Funktionalitaet benoetigt, wird die klasse erweitert oder eine neue abgeleitet, nichts anderes. Leider ja, das ist ein
Hoher Aufwand, der sich aber in der Wartung bezahlt macht. Cheers Mschmidt |
AW: class helper
Mit Hilfe von DSharp kann man von TComponent abgeleitete Klassen sehr einfach um Properties erweitern:
Delphi-Quellcode:
Dahinter steckt nicht viel mehr als ein Dictionary, in dem die Werte für die Instanzen gespeichert werden, inklusive FreeNotification, um die Werte für freigegebene Instanzen zu löschen.
unit ListBoxExtension;
interface uses DSharp.Core.DependencyProperty, StdCtrls; type TListBoxHelper = class helper for TListBox private class var FTestProperty: TDependencyProperty; class function GetTestProperty: TDependencyProperty; static; function GetTest: string; procedure SetTest(const Value: string); protected class property TestProperty: TDependencyProperty read GetTestProperty; public property Test: string read GetTest write SetTest; end; implementation { TListBoxHelper } function TListBoxHelper.GetTest: string; begin Result := TestProperty.GetValue(Self).AsString; end; class function TListBoxHelper.GetTestProperty: TDependencyProperty; begin if not Assigned(FTestProperty) then FTestProperty := TDependencyProperty.RegisterAttached('Test', TypeInfo(string), TListBox); Result := FTestProperty; end; procedure TListBoxHelper.SetTest(const Value: string); begin TestProperty.SetValue(Self, Value); end; end. |
AW: class helper
Zitat:
|
AW: class helper
Zitat:
|
AW: class helper
Hinweis: Der letzte Beitrag in diesem Thema ist älter als ein halbes Jahr.
Ich erlaube mir, trotzdem zu schreiben. Falls das nicht ok bist, einfach löschen :-) Ich sehe die Problematik, dass Instanzvariablen "angeblich" nicht erlaubt sind, nicht: Was hält mich denn davon ab, eine
Delphi-Quellcode:
-Klassenvariable zu deklarieren, die als Schlüssel eben die Instanz selbst hält?
TDictionary
Konkretes Beispiel: Ein TButtonHelper soll mir ermöglichen, dass jeder Button weiß, wann er das letzte mal geklickt worden ist:
Delphi-Quellcode:
In meiner Anwendung kann ich nun problemlos sagen
TButtonHelper = class helper for TButton
private class var lastPressedDictionary: TDictionary<TButton, TDateTime>; [...] property lastClicked: TDateTime read GetlastClicked write SetlastClicked; end;
Delphi-Quellcode:
. Natürlich ist das etwas aufwändiger als die Möglichkeit, einfache Instanzvariablen in einer Helper-Klasse zu haben, aber das beste, was ich kenne.
Button99.lastClicked := Now(); Button123.lastClicked := Yesterday();
In der Praxis habe ich bei VCL-Komponenten natürlich noch eine Art "enable/disableHelperFunctionality()" da man das TDictionary ja auch wieder abbauen sollte... |
AW: class helper
Zitat:
|
AW: class helper
Zitat:
Delphi-Quellcode:
aus DSharp zu machen.
TDependencyProperty
Gruß, Sven |
AW: class helper
Elaborieren Sie.
|
AW: class helper
Zitat:
|
AW: class helper
Zitat:
Zitat:
Delphi-Quellcode:
ableiten (wegen
TComponent
Delphi-Quellcode:
).
FreeNotification
Gruß, Sven |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:06 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