|
Antwort |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#21
Zitat von .chicken:
Also wie schreibe ich ein Event für meinen Server, wenn ich ihn zur Laufzeit erstelle?
Ich werde im folgenden einfach mal auf Beides eingehen. Das Ereignis an sich ist nichts, was Du wirklich programmieren musst. Du legst eigentlich nur fest, wann die Ereignisbehandlung ausgelöst wird. Das ist schon alles. Bleibt das Problem der Ereignisbehandlung. Hier gibt es ganz verschiedene Ansätze. Der unter Delphi typische besteht in einem Callback. Callback kannst Du dabei wirklich als Rückruf übersetzen. Jmd. der sich für ein Ereignis interessiert hinterlässt seine "Nummer" (genau gesagt ist es eine Adresse) und wird "zurückgerufen", wenn das Ereignis eintritt. An sich ist dies natürlich (mehr oder weniger) immer der Weg, den man verwendet. Der (hauptsächliche) Unterschied liegt darin, wie man nun die Rückrufnummer hinterlässt. Dabei ist der Delphi-typische Weg die Verwendung eines Methodenzeigers. Ein Methodenzeiger speichert die Adresse einer Methode. Das ist ein eigener Datentyp, der einfach eine Adresse speichert. Du weißt dann, dass eine solche Adresse auf eine Methode zeigt und wie deren Signatur aussieht. Du weißt also welche Parameter Du übergeben musst und was für ein Ergebnis Du bekommst (keins wenn es eine Procedure ist). Ein Methodenzeiger wird wie folgt deklariert:
Delphi-Quellcode:
Wie Du hier siehst, werden Methodenzeiger als Datentyp deklariert. Du gibst einfach einen Namen an und die eigentliche Deklaration besteht aus dem Schlüsselwort procedure oder function gefolgt von den Argumenten (soweit vorhanden) und für Funktionen dem Rückgabetyp. Der deutliche Unterschied zu normalen Methoden besteht hier schon darin, dass Du keinen Namen der Methode angibst. Zudem wird immer das Suffix of object angehangen.
type
TMethodenZeiger = procedure(Argument1: Typ1; ... ArgumentN: TypN) of object; // oder auch TMethodenZeiger2 = function(Argument1: Typ1; ... ArgumentN: TypN): TRueckgabeTyp of object; Lässt Du Letzteres weg, so handelt es sich um einfach Funktionszeiger. Der Unterschied zwischen Funktions- und Methodenzeiger ist dabei recht einfach erklärt, Methoden gehören immer zu einem Objekt (Instanz einer Klasse), Funktionszeiger tun das nie! Beide sind in Delphi unterschiedlich aufgebaut und müssen deswegen unterschieden werden (Methodenzeiger verwenden ein verstecktes Argument, das Objekt). Der Unterschied besteht also darin, dass Du einem Methodenzeiger nur Funktionen und Prozeduren (deren Adresse) zuweisen kannst, die zu der Instanz einer Klasse gehören. Umgekehrt kannst Du Prozeduren und Funktionen, die zu einer Klasse gehören aber nie einem Funktionszeiger zuordnen. Wie gesagt, Delphi verwendet i.d.R. immer Methodenzeiger. Wie man die deklariert hat, hast Du schon gesehen. Nach der Deklaration kannst Du die wie jeden anderen Datentypen auch verwenden und Variablen von diesem Typ anlegen. Diese Variablen können natürlich einen Wert annehmen und wie gesagt, dieser muss eine Adresse auf eine Methode (Prozedur oder Funktion eines Objekts) sein. Zudem muss die Signatur der Methode mit der deklarierten übereinstimmen (also müssen gleichviele Parameter in gleicher Reihenfolge und mit gleichem Typ übergeben werden). Typischerweise legt man in Klassen alle Variablen mit geringster Sichtbarkeit (private) an (auf die Gründe gehe ich nicht näher ein, hier wäre ein Tutorial zur OOP nötig). Die eigentlichen Lese- und Schreibzugriffe delegiert man (Stichwort property). Ein Delphi property wirkt nach außen wie eine Variable, der Zugriff kann jedoch an eine Methode oder Variable delegiert werden.
Delphi-Quellcode:
So ungefähr könnte das dann aussehen. Hier wird eine private Variable FVariable vom Typ TTyp angelegt. Den gleichen Typ haben die beiden properties (aber andere Namen). Dem Schlüsselwort property folgt etwas, dass wie eine normale Variablendeklaration aussieht (property Variable: TTyp). Dem wiederum folgt die Delegation des Lesens und/oder Schreibens (mindestens eine Eigenschaft muss hier delegiert werden). Im ersten Fall würde beim Lesen von Variable direkt die Instanzvariable FVariable gelesen werden. Würdest Du Variable einen Wert zuweisen (schreiben), dann würde hier die Methode setVariable aufgerufen werden. Der Parameter hat dabei automatisch den Wert, den Du setzen wolltest.
type
TKlasse = class(TObject) private FVariable: TTyp; protected procedure setVariable(const FValue: TTyp); public property Variable: TTyp read FVariable write setVariable; property VariableRO: TTyp read FVariable; end; Hier siehst Du auch gleich warum man das macht, so ist VariableRO ReadOnly. Hier wurde nur das Lesen delegiert. Würdest Du versuchen diesen Wert für eine Instanz zu schreiben, wird Dir ein Fehler (schon zur Compilezeit) gemeldet. Aber auch das Delegieren macht Sinn. So kann setVariable prüfen, ob der übergebene Wert überhaupt gültig ist. Dies kann wichtig sein, wenn es Einschränkungen der gültigen Werte gibt. Auch das Lesen eines Wertes kann natürlich an eine Funktion delegiert werden. So wäre z.B. eine Eigenschaft Mittelwert denkbar, die Du natürlich leicht bei Bedarf berechnen kannst (statt sie in einer Variable zu speichern und bei allen Änderungen zu aktualisieren). Ja, das gleiche wird meist auch mit Methodenzeigern gemacht. Allerdings werden die Zugriffe hier meistens direkt an die Variable deklariert (nur damit Du dich im Folgenden nicht wunderst). So, alles zusammen ergibt jetzt die Ereignisbehandlung. Du legst einfach eine Klasse an, die ein property OnEventX besitzt. Dieses ist vom Typ ein Methodenzeiger und speichert die Rückrufnummer für die Ereignisbehandlung (in einer Variable). Tritt jetzt Dein Ereignis ein, so schaust Du nach, ob eine gültige Rückrufnummer hinterlegt wurde. Ist dies der Fall, rufst Du dort an und teilst das Ereignis mit. Ist dies nicht der Fall, so kannst Du niemanden rückrufen und musst entsprechend nichts machen. Das ganze mal komplett:
Delphi-Quellcode:
Das sind jetzt erstmal nur die Datentypen. Du hast einfach einen Datentypen als Methodenzeiger, eine Klasse, deren Instanzen zurückgerufen werden können und eine Klasse, die die Rückrufe durchführt, sobald etwas bestimmtes passiert. In der letzten ist die weitere Funktionalität durch eine Methode doFoo angedeutet. doFoo könnte z.B. Auslöser der Ereignisbehandlung sein.
type
TRückruf = procedure(const arg1: String) of object; TCallMe = class(TObject) public procedure callMe(const t: String); end; TKlasseMitEreignis = class(TObject) private FRückrufAdresse: TRückruf; ... public procedure doFoo; .... property OnEreignis: TRückruf read FRückrufAdresse write FRückrufAdresse; end; Die Implementierung von TCallMe ist hier völlig egal. Stell Dir einfach vor, dass die Klasse ein ShowMessage mit dem Argument t macht, sobald die Methode callMe aufgerufen wird. Bleibt noch der Aufruf der Ereignisbehandlung:
Delphi-Quellcode:
So sieht dann einfach der Rückruf aus. Du kannst auf die Variable, die vom Typ ein Methodenzeiger ist wie auf eine normale Methode zurückgreifen. Mit dem assigned wird überprüft, ob die Adresse <> nil ist. Dies ist der Fall, sobald einmal eine gültige Adresse zugewiesen wurde. Nil (0) ist die einzigste verbotene Adresse. Auf einem 32-Bit Rechner bleiben damit (2^32 - 1) Adressen übrig (so gute 4,2 Mrd.). Das heißt aber nicht, dass jede Adresse <> nil gültig ist. Weißt Du eine Adresse zu, die zu einem Objekt gehört, so ist die nur gültig, bis Du das Objekt löscht. Du solltest Dich dann vor dem Löschen des Objekts darum kümmern, dass Du dort, wo es zurückgerufen wird die Rückrufnummer wieder auf nil setzt. Ansonsten bleibt die alte Rückrufnummer gespeichert, aber der Anschluss, der zurückgerufen wird wurde schon entfernt. Das gibt dann ein Problem (eine Exception).
procedure TKlasseMitEreignis.doFoo;
begin ... // Benachrichtigung // prüfen ob eine gültige Rückrufadresse zugewiesen wurde if assigned(OnEreignis) then begin // Rückruf einer Prozedur, die ein Argument vom Typ String bekommt self.OnEreignis('WAS AUCH IMMER'); end; // if assigned(OnEreignis) end; Zu guter Letzt bleibt noch das setzen der Variable. Das schauen wir uns gleich am Beispiel an:
Delphi-Quellcode:
Natürlich solltest Du die Instanzen nicht in lokalen Variablen speichern, wie es hier der Fall ist, sonst wären die nach dem Verlassen der Methode eh unerreichbar und sollten hier schon wieder frei gegeben werden (anders gesagt, das Beispiel zeigt etwas unsauberes, nicht so nachmachen ).
var klasseMitEreignis: TKlassesMitEreignis;
rückrufKlasse: TRückruf; begin // neue Instanzen erstellen klasseMitEreignis := TKlasseMitEreignis.Create; rückrufKlasse := TRückruf.Create; // eigentliches Registrieren der Rückruf-Adresse klasseMitEreignis.OnEreignis := rückrufKlasse.callMe; .... end; Das Prinzip sollte aber klar sein. Eine Sache ist hier jetzt aber ganz schlecht! Wie gesagt, es ist der Delphi-Standardweg. Trotzdem hast Du das Problem, dass Du nur eine Variable hast, also nur eine Rückrufadresse speichern kannst. Natürlich kannst Du für jede mögliche Rückrufadresse eine eigene Variable vorsehen, aber das verschiebt nur das Problem (man weiß nicht immer wie viele Spieler wirklich am Spiel teilnehmen wollen). Besser ist das Observer-Pattern zu verwenden. Dieses Entwurfsmuster beschreibt zwei Rollen, das Observable (beobachtbares Objekt) und die Observer (Beobachter). Ein Observable bietet dabei die Möglichkeit, dass sich Beobachter über eine bestimmte Schnittstelle registrieren und wieder deregistrieren können. Observer registrieren sich also beim Observable und alle registrierten Observer werden werden vom Observable zurückgerufen. Wie das genau geschieht (wie die registrierten Observer verwaltet und rückgerufen werden) ist dabei nicht durch das Pattern vorgegeben (Pattern definieren nur ein Problem und eine allgemeingültige Lösung, die unabhängig von der Implementierung ist!). Somit ist nur eindeutig bestimmt, was für eine Technik verwendet wird. Wie Du es z.B. in Delphi realisieren kannst, kannst Du dem einen Thread (hatte den Link denke ich schon gepostet) entnehmen. |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#22
Oh mein Gott, wie kompliziert ist das denn...ich will doch nurn Ereignis erstellen o.O
Wo schreib ich denn jetzt zB rein was passiert wenn das Ereignis in Kraft tritt? Sorry aber das kapier ich grad ma garnich! Trotzdem danke fuer diene sehr ausfuehrliche Antwort! |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#23
Zitat von .chicken:
Oh mein Gott, wie kompliziert ist das denn...ich will doch nurn Ereignis erstellen o.O
Wo schreib ich denn jetzt zB rein was passiert wenn das Ereignis in Kraft tritt? Um es hier nochmal einfach zu sagen (gelöst vom Code), Du hast zwei Rollen, Server und Client. Der Server kennt eintretende Ereignisse genau und benachrichtigt alle, von denen er weiß, dass sie sich dafür interessieren. Die Clienten wiederum registrieren/verbinden sich mit dem Server. Das heißt, dass sie sagen "Hallo, ich bin XYZ, bitte benachrichtige mich bei Ereignissen". Das ganze muss der Server sich merken (der muss ja wissen wer alles benachrichtigt werden möchte). Dazu schreibt er einfach alle Interessenten in eine Liste. Tritt jetzt das Ereingis ein, so schaut der Server in diese Liste. Ist die Leer, will's keiner wissen, er hat nichts zu tun. Sonst geht der einfach alle durch, die in der Liste stehen und benachrichtigt die. Beendet ein Client das Spiel, dann meldet der sich einfach beim Server ab und damit wird sein Name dann von der Liste genommen. Das ist die grobe Idee. An sich ist das aber ein sehr konkretes Beispiel (und natürlich auf dein Pokerspiel bezogen). Abstrakter würde man nicht von einem Server und Clienten sprechen, sondern davon, dass es einen gibt, der Benachrichtigt (Observable) und keinen, einen oder viele die benachritigt werden wollen (Observer). Die Anzahl der Observer ist nicht bekannt (Meldet sich ein Spieler, 10 oder 1000?), aber auch egal. Jeder der sich meldet kommt auf die Liste und jeder der sich abmeldet kommt wieder runter. Hat man also irgendeine Möglichkeit jmd. auf die Liste zu setzen und zu entfernen, kann man so beliebig viele (eben auch keinen) benachrichtigen, sobald ein Ereignis eintritt. Wer wen worüber benachrichtigt ist erstmal egal, das Prinzip ist immer das gleiche. Hast Du das Prinzip soweit verstanden? Wenn nicht nachfragen! Das ganze musst Du jetzt noch in Code umsetzen. Dabei gibt es verschiedene Probleme. Eine Trennung kann man hier sofort sehen, es muss Objekte geben, die sich benachrichtigen lassen wollen (die Observer) und etwas, dass die Benachrichtigung auslöst (Observable). Das Observable-Objekt muss zudem eine Möglichkeit haben, dass sich hier jmd. für eine Benachrichtigung melden/abmelden kann. Das Problem dabei ist, dass Du (wie gesagt) nicht weißt, wer jetzt eigentlich benachrichtigt werden möchte. Mal ist sind es Spieler A, B und C, dann wieder D, E und F und dann A und E. Das Problem, dass Du nicht weißt wieviele es sind lässt sich leicht über geeignete Strukturen lösen. Hier wäre es sicherlich die Liste. Eine Liste speichert einfach eine beliebige Anzahl von gleichartigen Elementen, entspricht ein wenig einem Array, nur ohne Größenbeschränkung. Problematischer ist, dass Du noch nicht weißt, wen Du benachrichtigen sollst. Hier musst Du Dir etwas überlegen, das man als Schnittstelle bezeichnen könnte/würde. Diese Schnittstelle ist verbindlich, sie legt fest, wie Du jmd. ansprechen kannst, der benachrichtigt werden möchte. Dabei musst Du alle Informationen speichern, die dazu nötig sind und wissen, wie Du über das Ereignis benachrichtigst. Stell Dir das einfach wie in einem Call-Center vor. Hier können sich Leute melden, die über den Verkaufstart der PS4 informiert werden wollen. Jetzt rufen die an und hinterlassen ihre Telefonnummer. Dazu müssen sie eine Möglichkeit haben, sich zu melden (die Telefonnummer für die Anmeldung). Das Call-Center speichert irgendwie die Nummern (wie ist egal). Natürlich muss es auch eine Möglichkeit geben, dass Du Dich wieder abmeldest, z.B. weil Du die X-Box 5D gekauft hast und Dich die PS4 nichtmehr interessiert. Startet der Verkauf, gehen die einfach die Liste durch und rufen jeden an der drauf steht. Jetzt müssen sie Dir aber noch mitteilen worum es geht. Da ist es dann gut, wenn Du auch verstehst was die meinen. Nach Möglichkeit solltest Du also jmd. am Telefon haben, der eine Sprache spricht, die Du verstehst. Kann auch sein, dass Du Dir noch denken kannst, dass der Verkaufsstart auf japanisch angekündigt wurde, ein Programm kann das nicht. Hier gibt es nur verstanden oder nicht verstanden. Am Besten überlegst Du Dir erstmal, was für Ereignisse Du im Moment berücksichtigen möchtest. Die Fragen die Du dabei stellen/beantworten solltes sind:
Poste erstmal die Ereignisse, dann kann man das leichter an einem Beispiel erklären. Und ansonsten frag einfach bei einzelnen Punkten, die Du nicht verstanden hast nach (ggf. halt immer nach dem nächsten Stück usw). |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#24
Also ich hab vom Server noch nicht viel!
Delphi-Quellcode:
Ich dachte jetzt eigentlich, dass ich vielleicht irgendwie sowas schreiben kann:
unit Server;
interface uses Controller; type TServer = class(TServerSocket) Private Public constructor Create; end; var Controller: TController; Server: TServer; implementation constructor TServer.Create; begin inherited Create; Controller := TController.Create; end; end.
Delphi-Quellcode:
Sodass wenn eine Nachricht eingeht "blablabla" ausgeführt wird.
MyEvent: Procedure (Sender: TObject) of Object; //richtig so? :D
Server.onClientRead := MyEvent; procedure TForm1.MyEvent(Sender:TObject); begin blablabla; end; Wie realisier ich das nun? Weil eigentlich müsste TServerSocket doch onClientRead kennen oder nicht? Aber die Auto-Vervollständigung gibt da garnix aus.... Verstehste jetzt wo mein Problem is? Wie der Server arbeitet hab ich im groben schon verstanden! Danke für deine Hilfe! |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#25
Zitat von .chicken:
Ich dachte jetzt eigentlich, dass ich vielleicht irgendwie sowas schreiben kann:
Delphi-Quellcode:
MyEvent: Procedure (Sender: TObject) of Object; //richtig so? :D
Server.onClientRead := MyEvent; MyEvent: Procedure... ist ganz schlecht! Der Doppelpunkt legt den Typ einer Variable fest. Dieser kann nicht einfach vom Typ procedure... sein, das würde zu einem Problem führen, dass ich nicht näher erläutern möchte. Einfach gesagt würden zwei Variablen mit diesem Typ nie kompatibel sein, da Delphi keinen einheitlichen Typen annehmen würde (wie gesagt, egal). Du müsstest erst einen Datentypen erzeugen:
Delphi-Quellcode:
Dann kannst Du Variablen von diesem Typen erstellen:
type
TMyEvent = procedure(Sender: TObject) of Object;
Delphi-Quellcode:
Ich hoffe Du siehst den Unterschied, so wie die nötigen Schlüsselwörter. An sich sollte jeder Datentyp auch ein Präfix (T für Typen, P für Zeiger) enthalten. Methodenzeiger bekommen ein T, da es sich um Referenzen handelt. Nur explizite Zeiger (Datentyp Pointer oder Dinge mit ^ wie ^Integer, ^Byte, ...) bekommen ein P vorgesetzt!
var
variable: TMyEvent; Damit ist immer klar, wann Du einen Typen meinst und wann eine Methode/Variable oder sonst was. Wichtig ist aber auch hier, dass Du die zwei Seiten (Observable und Observer) unterscheidest. Die Benachrichtigung wird bereits durch TServerSocket ausgelöst. Das heißt, TServerSocket ist bereits ein fertiger Observer. Was noch fehlt ist die Methode, die benachrichtigt werden soll, also der Observer. Welche Signatur die Methode haben muss kannst Du der OH entnehmen, dort unter Ereignisse findest Du das OnClientRead-Event und dessen Datentyp. Folgst Du dem, so siehst Du welche Argumente (z.B. Sender: TObject bei einem TNotifyEvent) Du übergeben musst. Ich gehe mal davon aus, dass Du da schon nachgeschaut hast und es sich hier um eine Methode handelt, die ein Argument von TObject bekommt. Streich die beiden Zeilen, die ich oben gepostet habe und dann stimmt auch der Anfang
Delphi-Quellcode:
Das kannst Du so stehen lassen, da ist alles korrekt. Was Du nun hast sind beide Seiten, TServerSocket bietet eine Möglichkeit jmd. zu benachrichtigen und TForm1 hat eine Methode, die benachrichtigt werden kann (TForm1.MyEvent). Was noch fehlt ist das Verknüpfen/Registrieren, so dass TServerSocket weiß, dass TForm1.MyEvent zurück gerufen werden soll.
procedure TForm1.MyEvent(Sender:TObject);
begin blablabla; end; Ok, jetzt wird mir klar was Du mit der Zeile meintest: server.onClientRead := MyEvent; Wobei Server eine Instanz von TServer sein muss und MyEvent eben die Methode von TForm1 (also die Zuweisung in einer Methode von TForm1 aufgerufen wird). Hier käme z.B. das OnFormCreate in Frage (wenn Server bereits erstellt wurde). Hier noch eine Bitte, bei solchen Zeilen wäre es immer schön, wenn Du ein wenig den Kontext angeben würdest. Wie Du gesehen hast ist (mir) hier nicht klar, was für einen Typ Server hat (usw.). |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#26
Edit: Natürlich doof wenn man die uses Klausel vergisst -.-
Trotzdem funzt es noch nicht wie ich will, habs nun nochmal n bissl geändert:
Delphi-Quellcode:
So ich glaube dass es jetzt eigentlich klappt, aber beim constructor gibt er immer n Fehler aus! (siehe Kommentar)
unit Server;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Spin, Controller, ScktComp; type TMyServer = class(TServerSocket) Private Public constructor Create; procedure MyReadEvent(Sender: TObject; Socket: TCustomWinSocket); end; var Controller: TController; Server1: TMyServer; //is das nicht n bisl komisch oder falsch? wenn man dann noch aufs oncreate ereignis guckt, wo dann der Server1.onClientRead zugewiesen wird...das is doch sicher nich ganz sauber oder? müsste ich nicht eigentlich im oncreate einfach TMyServer.onClientRead angeben? (das funzte aber nicht) implementation constructor TMyServer.Create; begin inherited Create; //Hier sagt er "Not enoough actual Parameters" Controller := TController.Create; Server1.onClientRead := MyReadEvent; end; procedure TMyServer.MyReadEvent(Sender: TObject; Socket: TCustomWinSocket); begin Showmessage('Klappt'); end; end. Außerdem gibt er ne komische Warnung aus: "Method Create hides virtual method of base type TServerSocket" Daraus werd ich noch nicht schlau! |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#27
Also, hab jetzt alles nochmal ueberarbeitet und auch einiges verbessern können!
Habe aber immernoch einen Fehler! Ich häng das Projekt einfach mal an! (Hab bisher eigentlich nur die 6Units "Server", "Client", "Controller", "Deck", "Karte", "Spieler" geschrieben aber hab die nun zum Testen und kompilieren mal in ein Projekt eingebunden!) Startet das Programm einfach mal und klickt auf Start Server. Dann kommtn Fehler und ich weiss nicht warum! Irgendwas mit Zugriffsverletzung aber was weiss ich nicht! |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#28
Zitat von .chicken:
Startet das Programm einfach mal und klickt auf Start Server. Dann kommtn Fehler und ich weiss nicht warum!
Irgendwas mit Zugriffsverletzung aber was weiss ich nicht! Ich glaube Dir ist der Unterschied zwischen Klasse und Exemplar noch nicht ganz klar. Die Variable aServer in der Unit Main, speichert den Verweis auf ein Exemplar. Die Klasse TMyServer ist nur eine Klasse. Rufst Du den Konstruktor der Klasse TMyServer auf, so wird ein Exemplar erzeugt und der Verweis zurückgegeben (wie bei einer Funktion). aServer.Create deutet der Compiler jetzt so, dass Du für das Exemplar aServer die Funktion Create aufrufen möchtest. Das Problem ist aber, dass Du aServer natürlich noch gar kein Exemplar zugewiesen hast. Die korrekte Form wäre also aServer := TMyServer.Create; Danach ist in aServer ein Verweis auf dieses neue Objekt gespeichert. Das heißt, dass Du irgendwann, sobald Du aServer einen anderen Wert zuweist oder es nicht mehr brauchst, aServer.Free aufrufen musst (um den Speicher wieder zu säubern). Wie Du damit schon siehst, sobald in aServer ein gültiger Verweis steht, kannst Du dann auch direkt auf die Methoden dieser Instanz zugreifen. Der Konstruktor wird aber immer direkt für eine Klasse aufgerufen (also TXYZ.Create) und das Ergebnis einer Variablen zugewiesen. Mit anderen Methoden solltest Du das nie tun! (es gibt statische Methoden, aber die sind ein anderes Thema). |
Zitat |
Registriert seit: 5. Dez 2006 459 Beiträge |
#29
Ach scheiße Sowas passiert mir immer wieder! Ja mit dem Objekt-Orientierten-Programmieren is schon richtig! Bei vielen Dingen weiß ich immer nich ganz was gemeint ist und unser InfoLehrer hat eh keine Peilung was Erklären überhaupt bedeutet!
Er sagt immer nur: "Und eure Aufgabe ist jetzt euch zu dem Thema Infos aus dem Internet zu suchen! Das ist auch ein Teil der Informatik! Blabla..." Naja ich infomier mich da mal und wenn du ein gutes Tut kennst kannstes mir gerne mitteilen (Hoffe das ist nicht zu lang... ) Edit: Ist der Code ansonsten denn auch so schlimm? |
Zitat |
Registriert seit: 13. Dez 2003 Ort: Berlin 1.756 Beiträge |
#30
Zitat von .chicken:
Naja ich infomier mich da mal und wenn du ein gutes Tut kennst kannstes mir gerne mitteilen
Zitat von .chicken:
Edit: Ist der Code ansonsten denn auch so schlimm?
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |