Ein kurzer Tip am Rande mit ein wenig Bla Bla drum rum:
Was ist ein Konstruktor?
In objektorientierten Sprachen (C++, Delphi) gibt es Objekte. Diese müssen irgendwo im Speicher des Programms abgelegt werden, d.h. Speicher muss reserviert und ggf. initialisiert werden, und genau das macht der Konstruktor.
Ein Konstruktor ist eine Funktion eines Objekts, die geufen wird, wenn ein Objekt erzeugt werden soll, da das häufig etwas komplizierter ist, als nur zu sagen "diese paar Byte gehören nun zu diesem Objekt".
Warum erzähle ich das in einem Tutorialforum für den GM?
Weil der GM auch sowas wie einen Konstruktor bereit stellt: Das Create Event.
Wenn man die Funktion
ruft, wird zunächst die Instanz von obj erzeugt, dann das Create Event ausgeführt, und erst dann wird wieder zu der Funktion zurückgekehrt, die instance_create() gerufen hat.
Und wo ist nun das Problem?
Der Unterschied zwischen einem Konstruktor in objektorientierten Programmiersprachen und dem Create Event im GM ist nun, dass man den Konstruktoren auch Parameter mitgeben kann, die sie dann verwenden können. Beim Create Event ist dies nicht möglich, da muss man, wenn man variable Werte von außen mitgeben möchte, erst das Create Event ablaufen lassen, und dann über
oder
herumtricksen.
Was ist nun aber, wenn das Objekt so entworfen wurde, dass das Create Event unbedingt einen oder mehrere bestimmte Parameter braucht? Und was, wenn dieses Create Event nicht gerade kurz ist?
Jedes Mal, wenn man eine Instanz dieses Objekts erzeugen will,
zu rufen ist recht umständlich, und bläht den Code nur auf.
Besser ist es zwar schon, dies alles in ein Skript auszulagern, aber auch diese Methode hat den Nachteil, dass erst das Create Event ausgeführt wird, und dann mit Variablen jongliert wird.
Und nu?
In gewissen Programmiersprachen gibt es immer eine Funktion mit dem Namen "main", die automatisch als erste bei Programmstart gerufen wird, und die das eigentliche Programm ist. Diese Funktion hat dann üblicherweise zwei Parameter: "argc" und "argv" (argument counter und argument vector). Die erste Variable gibt an, wieviele Parameter dem Programm übergeben wurden, der zweite enthält dann die Parameter in einem Array aus Strings (oder so ähnlich). Der GM hat das mit parameter_count() und parameter_string() übrigens auch.
Auf dieses Prinzip kann man nun jedenfalls bei dem Problem mit dem Konstruktor zurückgreifen:
Man richtet sich eine globale Variable "argv" ein,
und benutzt diese als Ablage für die Parameter.
Nun kann man sich einen "Konstruktor" wie folgt schreiben:
Alles anzeigen
und im Create Event dann die Parameter auslesen:
Und schon kann man über
Instanzen erzeugen und gleichzeitig Parameter übergeben.
Ich möchte nun aber in unterschiedlichen Situationen unterschiedliche Parameter übergeben.
Kein Problem. Entweder man reserviert sich auch "argc" (oder eine andere Variable) als weitere globale Variable oder nutzt "argv[0]", um eine Zahl quasi als "Konstruktor-ID" zu übergeben. D.h. für jede unterschiedliche Situation, in der man einen anderen Konstruktor braucht, schreibt man sich eine eigene Funktion "obj_foo_createN()", und jede schreibt dann eine eigene Zahl in argc oder argv[0]. Dann prüft man im Create Event diese Zahl, und je nach dem, welche da steht, wertet man die übrigen Werte von argv aus.
Oder man bleibt bei einem Konstruktor, und nutzt argument2, um die ID des Konstruktors anzugeben, den man möchte.
Ich mag aber keine globalen Variablen
Geht auch ohne, aber die Methode mag ich nicht, deswegen reiße ich sie nur mal kurz an:
Man erstellt sich ein Objekt "obj_Konstruktor" oder "obj_fooK", erzeugt davon im Konstruktor eine Instanz, schreibt die übergebenen Parameter dort rein, und erstellt dann das eigentliche Objekt. Dieses holt sich nun seine Parameter aus dem Konstruktor-Objekt, welches im Anschluss wieder gelöscht wird.
Da das nur gut geht, wenn ein Objekt in seinem Create Event keine anderen Instanzen von sich selbst erzeugen soll, und weil dabei ständig temporäre Instanzen erzeugt und wieder gelöscht werden, präferiere ich doch eher die Lösung mit der einen globalen Variable.
Was ist ein Konstruktor?
In objektorientierten Sprachen (C++, Delphi) gibt es Objekte. Diese müssen irgendwo im Speicher des Programms abgelegt werden, d.h. Speicher muss reserviert und ggf. initialisiert werden, und genau das macht der Konstruktor.
Ein Konstruktor ist eine Funktion eines Objekts, die geufen wird, wenn ein Objekt erzeugt werden soll, da das häufig etwas komplizierter ist, als nur zu sagen "diese paar Byte gehören nun zu diesem Objekt".
Warum erzähle ich das in einem Tutorialforum für den GM?
Weil der GM auch sowas wie einen Konstruktor bereit stellt: Das Create Event.
Wenn man die Funktion
ruft, wird zunächst die Instanz von obj erzeugt, dann das Create Event ausgeführt, und erst dann wird wieder zu der Funktion zurückgekehrt, die instance_create() gerufen hat.
Und wo ist nun das Problem?
Der Unterschied zwischen einem Konstruktor in objektorientierten Programmiersprachen und dem Create Event im GM ist nun, dass man den Konstruktoren auch Parameter mitgeben kann, die sie dann verwenden können. Beim Create Event ist dies nicht möglich, da muss man, wenn man variable Werte von außen mitgeben möchte, erst das Create Event ablaufen lassen, und dann über
oder
herumtricksen.
Was ist nun aber, wenn das Objekt so entworfen wurde, dass das Create Event unbedingt einen oder mehrere bestimmte Parameter braucht? Und was, wenn dieses Create Event nicht gerade kurz ist?
Jedes Mal, wenn man eine Instanz dieses Objekts erzeugen will,
zu rufen ist recht umständlich, und bläht den Code nur auf.
Besser ist es zwar schon, dies alles in ein Skript auszulagern, aber auch diese Methode hat den Nachteil, dass erst das Create Event ausgeführt wird, und dann mit Variablen jongliert wird.
Und nu?
In gewissen Programmiersprachen gibt es immer eine Funktion mit dem Namen "main", die automatisch als erste bei Programmstart gerufen wird, und die das eigentliche Programm ist. Diese Funktion hat dann üblicherweise zwei Parameter: "argc" und "argv" (argument counter und argument vector). Die erste Variable gibt an, wieviele Parameter dem Programm übergeben wurden, der zweite enthält dann die Parameter in einem Array aus Strings (oder so ähnlich). Der GM hat das mit parameter_count() und parameter_string() übrigens auch.
Auf dieses Prinzip kann man nun jedenfalls bei dem Problem mit dem Konstruktor zurückgreifen:
Man richtet sich eine globale Variable "argv" ein,
und benutzt diese als Ablage für die Parameter.
Nun kann man sich einen "Konstruktor" wie folgt schreiben:
GML-Quellcode
und im Create Event dann die Parameter auslesen:
Und schon kann man über
Instanzen erzeugen und gleichzeitig Parameter übergeben.
Ich möchte nun aber in unterschiedlichen Situationen unterschiedliche Parameter übergeben.
Kein Problem. Entweder man reserviert sich auch "argc" (oder eine andere Variable) als weitere globale Variable oder nutzt "argv[0]", um eine Zahl quasi als "Konstruktor-ID" zu übergeben. D.h. für jede unterschiedliche Situation, in der man einen anderen Konstruktor braucht, schreibt man sich eine eigene Funktion "obj_foo_createN()", und jede schreibt dann eine eigene Zahl in argc oder argv[0]. Dann prüft man im Create Event diese Zahl, und je nach dem, welche da steht, wertet man die übrigen Werte von argv aus.
Oder man bleibt bei einem Konstruktor, und nutzt argument2, um die ID des Konstruktors anzugeben, den man möchte.
Ich mag aber keine globalen Variablen
Geht auch ohne, aber die Methode mag ich nicht, deswegen reiße ich sie nur mal kurz an:
Man erstellt sich ein Objekt "obj_Konstruktor" oder "obj_fooK", erzeugt davon im Konstruktor eine Instanz, schreibt die übergebenen Parameter dort rein, und erstellt dann das eigentliche Objekt. Dieses holt sich nun seine Parameter aus dem Konstruktor-Objekt, welches im Anschluss wieder gelöscht wird.
Da das nur gut geht, wenn ein Objekt in seinem Create Event keine anderen Instanzen von sich selbst erzeugen soll, und weil dabei ständig temporäre Instanzen erzeugt und wieder gelöscht werden, präferiere ich doch eher die Lösung mit der einen globalen Variable.
