![]() |
Delphi-Version: 2010
"Namespace" innerhalb einer Klasse
So, ich mal wieder :)
Habe mir eine Animation-Klasse geschrieben und bin gerade dabei das class helper Konstrukt zu nutzen, da es sich hier echt wunderbar anbietet. Und zwar würde ich gerne zwei Methoden an alle Klassen "anhängen", sodass folgendes möglich ist:
Delphi-Quellcode:
An und für sich habe ich mir das so vorgestellt:
BeliebigesObject.Animate(...);
Delphi-Quellcode:
Nun kann es ja aber sein, dass es eine andere Methode gibt die schon so heißt, da Animate sehr allgemein klingt. Nun will ich vor das Animate aber nicht einen beliebigen String hinhängen, dass dieser sehr wahrscheinlich über eine ganze Anwendung hinweg einmalig ist, sondern ich hatte mir eher folgendes vorgestellt:
TObjectAnimator = class helper for TObject
public procedure Animate(); end;
Delphi-Quellcode:
Wäre Animator eine Klasse, so liesen sich ja auch weiter Methoden ohne Probleme hinzufügen. Allerdings kann ich in Animate nicht einfach auf Self (also BeliebigesObject) zugreifen, außer ich übergebe das. Gibt es hier nicht ein Namespace-Konstrukt, welches mir das schöner lösen könnte? Über Klassen fange ich mir einfach zu viele unschöne Probleme ein imho.
BeliebigesObject.Animator.Animate(...);
// oder BeliebigesObject.Animator.Stop(); |
AW: "Namespace" innerhalb einer Klasse
Delphi-Quellcode:
TObjectAnimator = class
private FObj: TTheObject; public constructor Create(Obj: TTheObject); procedure Animate(); end; TObjectAnimatorHelper = class helper for TTheObject public function Animator: TTheObject; end; function TObjectAnimatorHelper.Animator: TTheObject; begin Result := ...; end; bezüglich der Speicherverwaltung; - entweder TObjectAnimator als Interface - eine globale Liste führen, wo alle Animatoren drin sind - der Animator gibt sich selber frei, nachdem er verwendet wurde und man erstellt in
Delphi-Quellcode:
immer wieder einen Neuen (empfehle ich aber nicht)
.Animator: TTheObject;
- falls TTheObject von TComponent abgeleitet ist, dann könnt man dieses zum Owner von TObjectAnimator machen und beim Zugriff auf
Delphi-Quellcode:
wird entweder ein neuer Animator erstellt oder ein in TTheObject vorhandener TObjectAnimator genutzt
.Animator: TTheObject;
- oder man nutzt nur einen einzigen globalen TObjectAnimator, der von
Delphi-Quellcode:
zurückgegeben wird ... vor dessen Rausgabe wird dem TObjectAnimator noch gesagt, für welches TTheObject er als nächstes verantwortlich ist (hier muß man aber aufpassen, daß nicht mehrere Animatoren gleichzeitig aufgerufen werden, aber wenn man in dem Animator eine Verschachtelung nicht zuläßt, dann wäre es noch relativ ungefährlich)
.Animator: TTheObject;
|
AW: "Namespace" innerhalb einer Klasse
Zitat:
Hier mal eine Klasse, die im Konstruktor ein Control übergeben bekommt und dann dieses Control animiert.
Delphi-Quellcode:
Der Einsatz eines Class-Helpers würde ich nicht in Betracht ziehen.
TAnimateControl = class(TObject)
private Fcontrol : TControl; public constructor Create(AControl:TControl); procedure Animate; property Muster:TAnimateMuster; // linksrum, rechtrum, oben-nach-unten, wasauchimmer property MaxCycles:integer; // max. Anzahl von Schritten property ScaleFactor:double; // "Stärke" der Bewegung property TimeStep:integer; // Zeitdauer zwischen den Animationsschritten ... end; |
AW: "Namespace" innerhalb einer Klasse
@shmia: Genau das wollte ich ja hier vermeiden ;) Finde es etwas direkter, wenn ich
Delphi-Quellcode:
aufrufe, als
Object.MachWas()
Delphi-Quellcode:
. Mir ist schon klar, dass das Geschmackssache ist, aber alles muss gehen :mrgreen:
Controller.MachWasMit(Object)
@himitsu: Es wird nur ein Animator verwendet, der sich um alles kümmert. Das habe ich schon. Nur ist diese Lösung mit einer weiteren Klasse nicht optimal, da der Benutzer immer noch blöde Sachen machen kann... Aber ich sehe schon, nachdem ihr beide auch keine direkte Lösung kennt, gibt es wohl keine. Dann muss ich es wohl doch etwas anders lösen. |
AW: "Namespace" innerhalb einer Klasse
Zitat:
Eigentlich braucht du sogar eine Mehrfachvererbung, da du nicht nur die Methode Animate haben willst, sondern auch noch ein (privates) Feld in dem der Animator steckt. Ein Class-Helper ist dazu aber grundsätzlich nicht in der Lage, weil sich dadurch das Objekt um 4 Bytes verlängern müsste. Delphi müsste schon das Konzept von ![]() Ich kann dir nur sagen, dass du mit Vererbung hier nicht weiterkommst. Richtig wäre "Komposition"; also so wie ich das oben gezeigt habe. Es ist auch weniger eine Geschmacksfrage, ob man lieber Vererbung oder eher Komposition verwendet, sondern die Komposition hat handfeste Vorteile: ![]() |
AW: "Namespace" innerhalb einer Klasse
Hm, magst zwar irgendwie recht haben, aber ich sträube mich noch etwas gegen den Gedanken :mrgreen: So wie ich das haben will, ists halt irgendwie schöner imho (wobei Schönheit halt immer relativ ist, ich weiß)
Wenn ich meine Komponente allerdings für frühere Delphi-Versionen veröffentlichen will, dann muss ich wohl oder übel auf diese class helper verzichten... Daher wird es wohl darauf hinauslaufen eben die Komposition zu verwenden, schade drum! |
AW: "Namespace" innerhalb einer Klasse
Du könntest auch den Originaltyp überdecken
|
AW: "Namespace" innerhalb einer Klasse
![]() Du kannst dort alles machen, wie in einer Funktion, der Du das Objekt übergibst. Diese Funktion wird allerdings an das Objekt "angepappt" und hat Zugriff auf dieses als "Self". Überschreiben von Methoden ist nicht möglich. |
AW: "Namespace" innerhalb einer Klasse
Zitat:
@mkinzler: Du meinst Vererbung? Das will ich nicht, da mein Animator allgemeingültig sein soll und alle Integer/Extended-Properties animieren können soll -- auch wenn ein User z.B. die "Tag"-Property angibt, der Animator machts ;) |
AW: "Namespace" innerhalb einer Klasse
Delphi-Quellcode:
Du könntest natürlich auch einen indirekten Namespace einführen, in Form von einem Namesprefix, welchen du allen deinen Methoden/Property vorstellst.
unit Unit9;
interface uses SysConst, SysUtils; type TAnimator = class private FAllowFree: Boolean; class var FSingleton: TAnimator; public procedure BeforeDestruction; Override; procedure Animate(); procedure Stop(); end; TObjectAnimator = class helper for TObject public function Animate: TAnimator; end; implementation procedure TAnimator.BeforeDestruction; begin if not FAllowFree then raise EAccessViolation.Create(SAccessViolationNoArg); end; function TObjectAnimator.Animate: TAnimator; begin Result := TAnimator.FSingleton; end; ... initialization TAnimator.FSingleton := TAnimator.Create; finalization TAnimator.FSingleton.FAllowFree := True; FreeAndNil(TAnimator.FSingleton); end.
Delphi-Quellcode:
type
TObjectAnimator = class helper for TObject public procedure AnimateAnimate(); procedure AnimateStop(); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:31 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