AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Singletons vererben

Ein Thema von sir-archimedes · begonnen am 27. Jan 2006 · letzter Beitrag vom 28. Jan 2006
Antwort Antwort
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#1

Singletons vererben

  Alt 27. Jan 2006, 18:59
Hallo,

ich habe eine "Basis-Singleton"-Klasse erstellt und möchte nun erweiterte Klassen entwickeln, welche das Basis-Verhalten ebenfalls besitzen. Kann ich irgendwie die Singleton-Eigenschaft nur in der Basis-Klasse kapseln und in den abgeleiteten Klassen ausschließlich die Funktionalität implementieren?

Ich denke, dass das ohne weiteres nicht gehen wird, da ich ja nur eine Instanz der Singleton-Klasse habe und für meine abgeleiteten Klassen jeweils eine neue Instanz bräuchte. Aber evtl. hat ja jemand dafür einen Workaround gefunden?

Wenn es nicht gehen sollte, werde ich in der Basisklasse halt die Singleton-Zugriffsmethoden via abstrakter Class-Funktion vorsehen und in den Unterklassen (ca 5) implementieren...

Viele Grüße,
Dominik
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#2

Re: Singletons vererben

  Alt 27. Jan 2006, 19:48
Hier wurde das ganze mit Templates gelöst und die entstehenden Probleme für jede andere Implementierung angesprochen. Ich nehme an, ohne Templates ist eine wirklich sichere Implementierung nicht ohne weiteres möglich, sonst hätte Schneeweiß das wohl anders gelöst. Für das ganze Type-Safety-Zeuch müsste ja der Typ der Nachfahren bereits im Basistyp bekannt sein (hat Schneeweiß über das Template realisiert) oder man müsste die entsprechenden Methoden (zumindest das Beschaffen der Instanz) in den Nachfahren type-safe reimplementieren. Wenn man als Instanzvariable den Basistyp benutzt, kommt man mit reimplementiertem Singleton-Konstruktor weiter, aber das ist ja schön der größte Teil des Singletons. Ein sicheres, vererbbares Singleton kann ich mir ohne Template kaum vorstellen, aber vielleicht bin ich nur zu sehr an C++-Eleganz gewöhnt Jedenfalls hat der Typ hier auch keine Möglichkeit gefunden, in Delphi ein Singleton zu schreiben, das type-safe ist *und* das seine Singleton-Eigenschaften vererben kann. Seiner Einleitung entnehme ich, daß es auch niemand anders geschafft hat, oder sein Wissen für sich behalten will.
Irgendwo schwirrt aber eine kranke Möglichkeit rum, Templates in Delphi zu simulieren. Das Ding ist zwar hässlich wie die Nacht und nicht annähernd in der Nähe von etwas, das man noch grob als "Benutzerfreundlichkeit" bezeichnen könnte, aber immerhin geht's irgendwie.
Außerdem bastelt jbg an etwas, aber ich weiß nicht, wie weit er ist und ob er es dir geben will, wenn's noch nicht ganz fertig ist

Aber eine ganz andere Sache: Wie willst du bei 5 verschiedenen Singleton-Nachfahren jeweils eine Instanz ermöglichen? Du bräuchtest dafür doch 5 Variablen, die über die Lebenszeit der Anwendung zugreifbar bleiben. Gibt es auch eine Möglichkeit, in Delphi statische Klassenmember zu deklarieren? Wenn nein, müsstest du doch eh deine Unit anpassen um 5 globale Variablen zur Verfügung zu stellen, die die Instanzen beinhalten.
  Mit Zitat antworten Zitat
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Singletons vererben

  Alt 28. Jan 2006, 10:19
Zitat von tommie-lie:
Hier wurde das ganze mit Templates gelöst und die entstehenden Probleme für jede andere Implementierung angesprochen.
Genau das ist halt das Problem - Templates gibt es ja leider nicht in Delphi...

Zitat von tommie-lie:
Jedenfalls hat der Typ hier auch keine Möglichkeit gefunden, in Delphi ein Singleton zu schreiben, das type-safe ist *und* das seine Singleton-Eigenschaften vererben kann.
Interessanter Artikel - auch wenn mir sein Ansatz zu Singletons nicht so wirklich gut gefällt.

Zitat von tommie-lie:
Irgendwo schwirrt aber eine kranke Möglichkeit rum, Templates in Delphi zu simulieren. Das Ding ist zwar hässlich wie die Nacht und nicht annähernd in der Nähe von etwas, das man noch grob als "Benutzerfreundlichkeit" bezeichnen könnte, aber immerhin geht's irgendwie.
Oh jee... Schön ist das wirklich nicht. Wenn ich mir vorstelle, diesen Ansatz für mehr als 2 Klassen zu machen, dann habe ich ne Menge Compiler-Direktiven dadrin. Gefällt mir so gar nicht

Zitat von tommie-lie:
Außerdem bastelt jbg an etwas, aber ich weiß nicht, wie weit er ist und ob er es dir geben will, wenn's noch nicht ganz fertig ist
Und ich kann mich immernoch nicht mit Templates anfreunden...

Zitat von tommie-lie:
Aber eine ganz andere Sache: Wie willst du bei 5 verschiedenen Singleton-Nachfahren jeweils eine Instanz ermöglichen? Du bräuchtest dafür doch 5 Variablen, die über die Lebenszeit der Anwendung zugreifbar bleiben. Gibt es auch eine Möglichkeit, in Delphi statische Klassenmember zu deklarieren? Wenn nein, müsstest du doch eh deine Unit anpassen um 5 globale Variablen zur Verfügung zu stellen, die die Instanzen beinhalten.
Ganz genau hier habe ich auch mein Problem gesehen. Leider kann Delphi nur Klassenfunktionen, aber keine Klassenvariablen. Damit könnte man diesen ganzen Singleton-Kram viel einfacher erledigen. Endlich mal etwas, wo ich Java besser finde

Naja - ich habe jetzt auf jeden Fall für alle Klassen eine eigene Singleton-Implementation vorgesehen. Damit habe ich dann weniger Probleme. Aber dazu hätte ich auch noch eine Frage:

Wenn ich meine Oberklasse so aussieht:
Delphi-Quellcode:
  TServiceController = class
    public
      class function Instance: TServiceController; virtual; abstract;
  end;
Wie kann ich dann diese Instanz-Funktion korrekt zu folgendem ableiten:
Delphi-Quellcode:
  
  TLoginServiceController = class(TServiceController )
    public
      procedure Login;
      class function Instance: TLoginServiceController;
  end;
So bekomme ich eine Compilerwarnmeldung. Wenn ich die Funktion overriden möchte, erhalte ich den Fehler, dass die Typen nicht zueinander kompatibel sind. Nun möchte ich aber auch nicht nur TServiceController zurückliefern, da ich dann immer casten muss... Wie mache ich das also?

Viele Grüße,
Dominik
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#4

Re: Singletons vererben

  Alt 28. Jan 2006, 11:17
Zitat von dominik.boehm:
Oh jee... Schön ist das wirklich nicht. Wenn ich mir vorstelle, diesen Ansatz für mehr als 2 Klassen zu machen, dann habe ich ne Menge Compiler-Direktiven dadrin. Gefällt mir so gar nicht
Mehr Compiler-Direktiven als Code?
Meine persönliche Einschätzung, auch in Bezug auf die Einleitung des Artikels, des Dingens ist, daß es eher eine Spielerei ist. Er ist Delphi-Fanatiker und hatte keinen Bock mehr, von C++lern ausgelacht zu werden, und deswegen hat er sich so einen Code zusammengeschustert. Wahrscheinlich ist er auch einer derjenigen, die immer behaupten, Delphi sei soooo cool, weil der Code viel übersichtlicher und lesbarer ist als der von C++. IMAO nicht sonderlich ernst zu nehmen, auch wenn er wohl so masochistisch ist, und sowas in Produktivcode einsetzt.

Zitat von dominik.boehm:
Und ich kann mich immernoch nicht mit Templates anfreunden...
Eigentlich ganz nette Freunde, wenn man sich mit ihnen ein Weilchen beschäftigt. Ich finde sie einfach praktisch, wenn es darum geht, irgendwelche Algorithmen oder Strukturen wirklich type-safe zu implementieren. Nie wieder typecasten
Aber sicherlich Gewöhnungssache.

Zitat von dominik.boehm:
Zitat von tommie-lie:
Aber eine ganz andere Sache: Wie willst du bei 5 verschiedenen Singleton-Nachfahren jeweils eine Instanz ermöglichen?
Ganz genau hier habe ich auch mein Problem gesehen. Leider kann Delphi nur Klassenfunktionen, aber keine Klassenvariablen.
Puh, dann hat mich mein Gedächtnis doch nicht getrügt und ich habe doch nicht ein wichtiges Feature von Delphi verpasst

Zitat von dominik.boehm:
Endlich mal etwas, wo ich Java besser finde
Oder C++

Zitat von dominik.boehm:
Naja - ich habe jetzt auf jeden Fall für alle Klassen eine eigene Singleton-Implementation vorgesehen. Damit habe ich dann weniger Probleme.
Entwickelst du das Projekt mit Delphi2006? Dann könnten dir zumindest die Code Templates der IDE ein wenig Copy&Paste-Arbeit ersparen (und das Code Template wäre wiederverwendbar und du müsstest es nicht irgendwo aus deinen alten Units rauskopieren, wenn du mal wieder mehrere Singletons brauchst).

Zitat von dominik.boehm:
Wenn ich die Funktion overriden möchte, erhalte ich den Fehler, dass die Typen nicht zueinander kompatibel sind. Nun möchte ich aber auch nicht nur TServiceController zurückliefern, da ich dann immer casten muss... Wie mache ich das also?
Beim überschreiben von virtuellen Methoden müssen die erweiterten Signaturen der Funktionen übereinstimmen. Dazu gehört auch der Rückgabewert und der Name (ergo die gesamte Deklaration muss identisch sein).
Was mir spontan einfällt:
Delphi-Quellcode:
TAncestorSingleton = class
protected
  class function _Instance(): TAncestorSingleton; virtual; abstract;
end;

TDerivedSingleton = class(TAncestorSingleton)
public
  class function Instance(): TDerivedSingleton;
protected
  class function _Instance(): TAncestorSingleton; virtual; override; // oder war das in Delphi ohne "virtual" bei "override"?
end;


implementation

TDerivedSingleton.Instance(): TDerivedSingleton;
begin
  Result := _Instance();
  // oder für die ganz ordentlichen:
  // Result := TDerivedSingleton(_Instance());
end;
Auch nicht schön, aber leider das einzige, was mir einfällt. Ich habe zum Beispiel auch noch keine wirklich schicke Factory in Delphi gesehen (eine Factory für mehr als eine Klasse). Entweder die Objekte müssen sich des Patterns bewusst sein (TDerivedSingleton hat eine eigene Class Function Instance(), oder bereits der Vorfahre muss über die Nachfahren informiert sein. Über eine wirklich elegante Lösung würde ich mich auch freuen, falls jemand eine hat (gescheite Smart Pointer wären dann nur noch das i-Tüpfelchen ).
  Mit Zitat antworten Zitat
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Singletons vererben

  Alt 28. Jan 2006, 11:25
Zitat von tommie-lie:
Entwickelst du das Projekt mit Delphi2006? Dann könnten dir zumindest die Code Templates der IDE ein wenig Copy&Paste-Arbeit ersparen (und das Code Template wäre wiederverwendbar und du müsstest es nicht irgendwo aus deinen alten Units rauskopieren, wenn du mal wieder mehrere Singletons brauchst).
Stimmt - wäre eine Idee. Aber irgendwie bin ich mit den Code-Templates noch nicht wirklich gut klargekommen. Habe mal 10 Minuten versucht mir ein kleines Template zu basteln, aber das hat nicht sofort probiert und weiter wichtig war es mir auch nicht.

Zitat von tommie-lie:
Beim überschreiben von virtuellen Methoden müssen die erweiterten Signaturen der Funktionen übereinstimmen. Dazu gehört auch der Rückgabewert und der Name (ergo die gesamte Deklaration muss identisch sein).
Was mir spontan einfällt:
Delphi-Quellcode:
TAncestorSingleton = class
protected
  class function _Instance(): TAncestorSingleton; virtual; abstract;
end;

TDerivedSingleton = class(TAncestorSingleton)
public
  class function Instance(): TDerivedSingleton;
protected
  class function _Instance(): TAncestorSingleton; virtual; override; // oder war das in Delphi ohne "virtual" bei "override"?
end;
1. es ist ohne virtual bei override
2. Das ist wirklich eine gute Idee. Ich kann ja da, wo ich die Oberklasse verwende, dann mit _Instance arbeiten und da wo ich die Unterklasse auch persönlich kenne mit Instance. Das hatte ich völlig übersehen - hatte in die Richtung gedacht, aber war nicht drauf gekommen . Danke
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#6

Re: Singletons vererben

  Alt 28. Jan 2006, 11:29
Zitat:
Ich habe zum Beispiel auch noch keine wirklich schicke Factory in Delphi gesehen (eine Factory für mehr als eine Klasse). Entweder die Objekte müssen sich des Patterns bewusst sein (TDerivedSingleton hat eine eigene Class Function Instance(), oder bereits der Vorfahre muss über die Nachfahren informiert sein.
Das geht sehr wohl. Ist zwar nicht wirklich hübsch, aber auch nicht häslich.
Da ich die Klassenregistrierung in der Delphi RTL extrem widerlich finde, habe ich
alzaimars IntegerDictionary genommen.(Beide wirklich seeehr praktische Klassen, btw)
Dort habe ich den Pointer auf die jeweilige Meta class (cast auf Integer) als Key abgelegt, der dazugehörige Wert ist die Instanz dieser Klasse.
Delphi-Quellcode:
type
   TSingleton = class
   protected
      constructor UglyHiddenCreate; virtual;
   public
      class function GetInstance : TSingleton;
      constructor Create; reintroduce;
   end;
   TSingletonClass = class of TSingleton;
implementation
uses
   csDictionary,
   SysUtils;

{ TSingleton }

constructor TSingleton.Create;
begin
   raise Exception.Create('bla bla...');
end;

constructor TSingleton.UglyHiddenCreate;
begin
   inherited Create();
end;

class function TSingleton.GetInstance: TSingleton;
const
   dictionary : TIntegerDictionary = nil;
var
   key : Integer;
   pointerToResult : Pointer;
begin
   if not Assigned(dictionary) then
      dictionary := TIntegerDictionary.Create();

   key := Integer(self);

   if not dictionary.Find(key, pointerToResult) then
   begin
      result := UglyHiddenCreate();
      dictionary.Add(key, result);
   end
   else
      Result := TSingleton(pointerToResult);
end;
2 TestKlassen:
Delphi-Quellcode:
uses
   uSingleton;

type
   TSingletonA = class(TSingleton)
   end;

   TSingletonB = class(TSingleton)
   end;
Der Beweis:
Delphi-Quellcode:
procedure TestIt(singletonClass : TSingletonClass);
var
   instance1,
   instance2 : TSingleton;
begin
   instance1 := singletonClass.GetInstance();
   instance2 := singletonClass.GetInstance();

   Writeln(Format('%s: instance1 = instance2 is %s',
                         [singletonClass.ClassName(),
                           BoolToStr(instance1 = instance2, True)]));
end;

begin
   TestIt(TSingletonA);
   TestIt(TSingletonB);
end.
Output
TSingletonA: instance1 = instance2 is True
TSingletonB: instance1 = instance2 is True


edit: Nachdem ich erst tommies Zitat vergass, hatte ich auch noch den TestCode mit dem StringDictionary hier abgeschickt
Robert Giesecke
  Mit Zitat antworten Zitat
sir-archimedes

Registriert seit: 2. Jan 2006
Ort: Münster
167 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Singletons vererben

  Alt 28. Jan 2006, 11:49
Zitat von Elvis:
Das geht sehr wohl. Ist zwar nicht wirklich hübsch, aber auch nicht häslich.
Da ich die Klassenregistrierung in der Delphi RTL extrem widerlich finde, habe ich
alzaimars IntegerDictionary genommen.(Beide wirklich seeehr praktische Klassen, btw)
Das sieht mir ja genau nach dem aus, was ich eigentlich gesucht hatte Sehr sehr geil! Danke
  Mit Zitat antworten Zitat
tommie-lie
(Gast)

n/a Beiträge
 
#8

Re: Singletons vererben

  Alt 28. Jan 2006, 12:05
@Elvis: Das einzig interessante an deinem Code ist das Dictionary. Bei Zuweisungen von GetInstance() findet nach wie vor ein Typecast statt. Ich bin immer noch der Meinung, daß die klassische C++-Lösung eleganter ist
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#9

Re: Singletons vererben

  Alt 28. Jan 2006, 12:06
Zitat von tommie-lie:
Ich bin immer noch der Meinung, daß die klassische C++-Lösung eleganter ist
Bestreitet ja auch keiner. Wir reden hier ja auch nur über Delphi.
Robert Giesecke
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:42 Uhr.
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