Klasse: protected, public usw.
-
Bei meinem Projekt hab ich eine Spriteklasse, die mehrere public-Funktionen und 2 protected Variablen hat. Jetzt ist es ziemlich mühsam, wenn man z.B. die Position des Sprites herausfinden will, muss man immer Sprite->GetRect()->x; eingeben (die GetRect-Funktion gibt ein &SDL_Rect zurück, indem die x-Koordinate gespeichert ist). Wäre es nicht einfacher, einfach Sprite->x zu schreiben und dafür öffentliche Variabeln zu erstellen? Mit Klassen hab ich eben noch nicht sehr viel Erfahrung. Ich weiss zwar, dass es zu Problemen kommen kann, wenn die Variabeln öffentlich zugänglich sind, doch wieso ist das eigentlich so? Weil sie aus Versehen geändert werden könnten? Ich denke, der Typ, von dem ich das habe, weiss schon Bescheid... Deshalb wollte ich euch fragen, wie ihr es handhabt mit Klassenfunktionen...
Ich freue mich auf eure Antworten...
-
Ich würde folgendes schreiben:
Sprite->getX(); Sprite->setX(wert); //bzw Sprite->X(); Sprite->X(wert);der Vorteil ist, dass man nicht ausversehen eine Variable ändert(wie du schon sagtest). Der nächste Vorteil ist, dass du innerhalb der funktion machen kannst, was du willst. wenn du was an der Klasse änderst, fällt das von aussen nicht auf.
//Beispiel class Sprite { float getX() { return GetRect()->x; } //oder float getX() { return x; } };Der letzte Punkt ist, dass es auch nicht immer möglich ist, eine öffentliche variable zu deklarieren. Manchmal müssen, wenn eine Variable geändert wurde, auch andere Werte angepasst werden. Nur weis das Objekt nicht, wann eine öffentliche Variable geändert wurde, und müsste dann entweder eine "update" funktion einbauen, die nach jeder Variablen änderung vom nutzer aufgerufen werden muss, oder bei jeder verarbeitenden funktion erstmal testen ob sich werte geändert haben. An der Stelle sind halt getter/setter sinnvoller, weil die alles automatisch erledigen können.
Nun stell dir noch vor, dass du eine klasse hast, wo getter/setter und öffentliche variablen gemischt werden. das ist der absolute Horror. das kann sich kein Mensch merken, und dann gilt meine Signatur

//nachtrag
Es gibt noch Propertys. das sind öffentliche Objekte, die die interne Variable nach aussen hin repräsentieren, und sich genauso verhalten, nur mit dem unterschied, dass sie keinen unkontrollierten zugriff bieten(man kann sie sich wie nen getter/setter paar mit verbesserter syntax vorstellen)
-
man sollte klassen jedoch nicht mit unnötigen get und set methoden aufblähen. anstatt es so wie mein vorposter zu machen hätte ich es so gemacht:
//Irgendeine Funktion in der du die X Koordinate des Sprites brauchst void foo() { Sprite sprite; SDL_Rect pos = sprite->getRect(); //... if(pos.x > sowieso) //... }Das erfordert keinen Stilpfusch und ist Leistungssparender als jedes ma die Get-methode aufzurufen.
-
@TravisG du schlägst genau das vor, wovon der threadstarter weg wollte
.Das erfordert keinen Stilpfusch und ist Leistungssparender als jedes ma die Get-methode aufzurufen.
ich seh hier keinens tilpfusch, klär mich auch. und in 99% aller Fälle ist meine Lösung nichtmal ansatzweise langsamer.
-
otze schrieb:
@TravisG du schlägst genau das vor, wovon der threadstarter weg wollte
.Das erfordert keinen Stilpfusch und ist Leistungssparender als jedes ma die Get-methode aufzurufen.
ich seh hier keinens tilpfusch, klär mich auch. und in 99% aller Fälle ist meine Lösung nichtmal ansatzweise langsamer.
ich meinte mit dem pfusch nicht deine lösung sondern das publicsetzen von attributen. er wollte zudem weg von if(sprite->getRect()->x > sowieso).
-
in der gefahr, dass du einen edit überlesen könntest weil du genau dann postest während ich editiere, schreib ich mal ne antwort mit nem beispiel:
findest du
//Kollision zwischen 2 Sprites abfragen bool checkForCollision(Sprite *sprite1,Sprite *sprite2) { if(sprite1.getX() > sprite2.getX() + sprite2.getW()) return false; if(sprite1.getY() > sprite2.getY() + sprite2.getH()) return false; if(sprite1.getX() + sprite1.getW() < sprite2.getX()) return false; if(sprite1.getY() + sprite1.getH()< sprite2.getY()) return false; return true; }schöner als
//Kollision zwischen 2 Sprites abfragen bool checkForCollision(Sprite *sprite1,Sprite *sprite2) { SDL_Rect s1 = sprite1->getRect(), s2 = sprite2->getRect(); if(s1.x > s2.x + s2.w) return false; if(s1.y > s2.y + s2.h) return false; if(s1.x + s1.w < s2.x) return false; if(s1.y + s1.h < s2.y) return false; return true; }?
-
TravisG schrieb:
otze schrieb:
@TravisG du schlägst genau das vor, wovon der threadstarter weg wollte
.Das erfordert keinen Stilpfusch und ist Leistungssparender als jedes ma die Get-methode aufzurufen.
ich seh hier keinens tilpfusch, klär mich auch. und in 99% aller Fälle ist meine Lösung nichtmal ansatzweise langsamer.
ich meinte mit dem pfusch nicht deine lösung sondern das publicsetzen von attributen. er wollte zudem weg von if(sprite->getRect()->x > sowieso).
die sache mit dem stilpfusch ist akzeptiert. aber das zweite hat er immernoch. wenn er nur einen wert brauch, dann ist das anlegen einer zusätzlichen variable nicht ganz so praktisch, denn dann wird das genauso aussehen, wie vorher auch.
@deinen zweiten post. das 2. ist schöner, aber auch mit meiner Lösung(siehe nachtrag propertys) zu erreichen. Ohne propertys würde aus einem "x" ein "x()" werden, und damit kann ich leben.
//edit zumal du auch gemeinerweise bei deinen beispielen auch noch bei der namenswahl rumpfuscht, sodass du das zweite beispiel noch kompakter machst

-
Vielen Dank für eure Hilfe!
@ TravisG: Ist es nicht ein bisschen unpraktisch, wenn man zu jedem Sprite noch ein extra SDL_Rect erstellen muss, das sich ja sowieso gleich wie das in die Klasse integrierte verhält? Bei einem Sprite gehts ja noch, aber wenn da bei einem 2D-Game Unmengen von Sprites vorhanden sind und man für jedes noch ein separates Rect erstellen muss (klar kann mans), dann finde ich es ziemlich umständlich...
@otze: Dein Vorschlag gefällt mir, ist jedoch die ganze relevante Problematik nur das mit dem Aus-Versehen-Ändern? Weil in der Klasse werde ich wohl nicht viel mehr als 8 Variabeln haben, deshalb sollte auch die Übersicht nicht gross in Gefahr sein...
Aber ja, ich weiss eben auch nicht... Mit GetX() und SetX(...) fahre ich wahrscheinlich nicht schlecht...
-
Nexus schrieb:
Bei meinem Projekt hab ich eine Spriteklasse, die mehrere public-Funktionen und 2 protected Variablen hat. Jetzt ist es ziemlich mühsam, wenn man z.B. die Position des Sprites herausfinden will, muss man immer Sprite->GetRect()->x; eingeben (die GetRect-Funktion gibt ein &SDL_Rect zurück, indem die x-Koordinate gespeichert ist). Wäre es nicht einfacher, einfach Sprite->x zu schreiben und dafür öffentliche Variabeln zu erstellen? Mit Klassen hab ich eben noch nicht sehr viel Erfahrung. Ich weiss zwar, dass es zu Problemen kommen kann, wenn die Variabeln öffentlich zugänglich sind, doch wieso ist das eigentlich so? Weil sie aus Versehen geändert werden könnten? Ich denke, der Typ, von dem ich das habe, weiss schon Bescheid... Deshalb wollte ich euch fragen, wie ihr es handhabt mit Klassenfunktionen...
Ich freue mich auf eure Antworten...
Die eigendliche Antwort ist, daß bei einem guten Programmdesign überhaupt keine Notwendigkeit bestehen sollte überhaupt auf die Variablen der Klasse zuzugreifen. Der Gedanke der Kapselung ist ja eben, alle relevanten Daten und Funktionen die die Klasse benötigt in selbiger zu vereinen. Sobald die Notwendigkeit besteht "von Aussen" auf Variablen einer Klasse zuzugreifen ist das zumindest ein Hinweis auf unsauberes Design.