Wir haben die objektorientierte Programmierung für Spieleentwickler im Allgemeinen und die spezifischen OOP-Prinzipien für Kohäsion und Kopplung besprochen. Lass uns einen Blick darauf werfen Verkapselung und wie es hilft, Code locker gekoppelt und wartungsfreundlicher zu halten.
Hinweis: Obwohl dieser Schnelltipp mit Java erklärt wird, sollten Sie in der Lage sein, in fast jeder Spielentwicklungsumgebung dieselben Techniken und Konzepte anzuwenden.
Einkapselung ist das Prinzip des Verdeckens von Informationen. Das ist die Implementierung (die internen Abläufe) eines Objekts sind für den Rest des Programms nicht sichtbar.
Ein bekanntes Beispiel für die Kapselung ist das Autofahren. Müssen Sie genau wissen, wie jeder Aspekt eines Autos funktioniert (Motor, Vergaser, Lichtmaschine usw.)? Nein, Sie müssen wissen, wie Sie das Lenkrad, die Bremsen, das Gaspedal usw. verwenden.
Ein anderes Beispiel ist die Suche nach einem Wert in einem Array. In Java können Sie Folgendes tun:
int myArray [] = 1, 2, 3, 5, 7, 9, 11, 13; Arrays.asList (meinArray) .contains (11);
Der obige Code wird zurückgegeben wahr
wenn der Wert 11
ist in myArray
, sonst wird es zurückkehren falsch
. Wie geht das? enthält ()
Methode arbeiten? Welche Suchtechnik verwendet es? Wird das Array vor der Suche vorsortiert? Die Antwort ist es spielt keine Rolle weil die genaue Implementierung der Methode verborgen ist.
Encapsulation hilft dabei, Code zu erzeugen, der lose gekoppelt ist. Da die Details ausgeblendet sind, können andere Objekte den Status und das Verhalten eines Objekts nicht direkt ändern.
Es ist auch sehr hilfreich, wenn Sie den Datentyp einer Variablen ändern müssen. Nehmen wir an, Sie haben sich für die Verwendung von a entschieden String
um die Zeit im Format "hh: mm: ss" zu verfolgen. Nach einer Weile merkt man das int
Sekunden repräsentieren könnte ein besserer Datentyp für die Zeit sein. Sie müssen nicht nur den Datentyp im Objekt ändern, sondern auch jedes Mal, wenn Sie im gesamten Programm auf die Zeit des Objekts verweisen!
Stattdessen können Sie sogenannte Getter- und Setter-Funktionen verwenden. Getter und Setter sind normalerweise kleine Funktionen, die jeweils eine Variable zurückgeben und setzen. Eine Getter-Funktion zum Abrufen der Uhrzeit würde folgendermaßen aussehen:
public String getTime () Rückkehrzeit;
Der Getter wird eine zurückgeben String
value: die Variable Zeit
. Jetzt, wenn wir uns ändern wollen Zeit
zu einem int, anstatt alle Aufrufe des Getters zu ändern, können wir einfach die Getter-Funktion ändern, um die int
Datentyp in ein String
Datentyp.
public String getTime () // Zeit in Stunden, Minuten und Sekunden aufteilen int Stunden = Zeit / 3600; int Rest = Zeit% 3600; int Minuten = Rest / 60; int Sekunden = Rest% 60; // // Kombiniere das Ergebnis in einen durch Doppelpunkt getrennten String und stelle Stunden + ":" + Minuten + ":" + Sekunden zurück;Das
%
Operator wird als Modulusoperator bezeichnet und gibt den Rest einer Division zurück. So 10% 3
würden zurückkehren 1
schon seit 10/3 = 3
mit einem rest von 1
. Die Getter-Funktion gibt jetzt a zurück String
und keiner der Aufrufe der Funktion muss sich ändern. Der Code ist daher wartungsfreundlicher.
Gehen wir zurück zum Beispiel eines Schiffs, das eine Kugel abfeuert, die im Kupplungsartikel eingeführt wurde. Denken Sie daran, dass wir ein Schiff wie folgt definiert haben:
/ ** * Die Schiffsklasse * / public-Klasse Schiff / ** * -Funktion - Führt das Verhalten (Aufgabe) beim Drehen des Schiffs * / public void rotate () // Code aus, der das Schiff dreht / ** * -Funktion - führt das Verhalten (Aufgabe) des Verschiebens des Schiffes * / public void move () // Code, der das Schiff bewegt / ** * Funktion - führt das Verhalten (Aufgabe) des Abfeuerns der Schiffswaffe * / public void fire ( ) // Code, mit dem das Schiff eine Kugel abfeuern lässt
Damit das Schiff eine Kugel abfeuern lässt, müssten Sie nur anrufen ship.fire ()
. Wie der Code das Abfeuern eines Geschosses implementiert, ist nicht wichtig, da es uns nur darum geht, ein Geschoss abzufeuern. Auf diese Weise müssen Sie nur die Methode ändern, wenn Sie den Code ändern möchten, um stattdessen einen Laserstrahl abzufeuern Feuer()
und nicht bei jedem anruf ship.fire ()
.
Auf diese Weise können Sie jeden Aspekt der Funktionsweise des Schiffes ändern, ohne die Verwendung des Schiffsobjekts an anderer Stelle ändern zu müssen.
Tetris hat verschiedene Möglichkeiten, mit Clearing-Linien umzugehen. Durch das Einkapseln des Verhaltens beim Löschen einer Zeile können Sie schnell die verwendete Methode ändern, ohne jede Verwendung neu schreiben zu müssen. Dadurch können Sie sogar die Methode der klaren Linien ändern, um verschiedene Spielmodi im Spiel zu erstellen.
Es gibt eine weitere Funktion der Kapselung, die den Zugriff auf ein Objekt verdeckt. Es gibt viele Situationen, in denen Sie keinen externen Zugriff auf den Status oder das Verhalten eines Objekts wünschen und es daher vor jedem anderen Objekt ausblenden möchten. Zu diesem Zweck können Sie Modifizierer für Zugriffsebenen verwenden, die den Zugriff auf Status und Verhalten von Objekten ermöglichen oder verbergen.
Zugriffsstufenmodifizierer definieren zwei Zugriffsebenen:
Öffentlichkeit
- Jedes Objekt kann jederzeit auf die Variable oder Funktion zugreifen.Privatgelände
- Nur das Objekt, das die Variable oder Funktion enthält, kann darauf zugreifen.(Es gibt eine dritte Ebene - geschützt
- aber wir werden das in einem zukünftigen Beitrag behandeln.)
Erinnern wir uns daran, dass ein Geist folgende Zustände hatte:
Farbe
Name
Zustand
Richtung
Geschwindigkeit
… Und wurde wie folgt definiert:
/ ** * Die Ghost-Klasse * / public class Ghost / ** * Funktion - verschiebt den Ghost * / public void move () // Code, mit dem der Ghost in die aktuelle Richtung bewegt wird / ** * Function - Ghost ändern direction * / public void changeDirection () // Code, der die Richtung des Ghosts ändert / ** * Funktion - Ghost-Geschwindigkeit ändern * / public void changeSpeed () // Code, der die Geschwindigkeit des Ghosts ändert / ** * Funktion - Ghost-Farbe ändern * / public void changeColor () // Code, der die Farbe des Ghosts ändert / ** * Funktion - Ghost-Status ändern * / public void changeState () // Code, der den Status des Ghosts ändert // Diese Funktion ebenfalls ruft die drei Funktionen changeDirection (), changeSpeed () und changeColor () auf
Schon seit Farbe ändern()
, changeSpeed ()
, und die Richtung ändern()
sind Hilfsfunktionen, auf die nicht von irgendwo anders zugegriffen werden darf, sondern innerhalb der Klasse. Wir können sie als definieren Privatgelände
Funktionen. Alle Zustände des Geistes können auch deklariert werden Privatgelände
da sie auch nicht von außerhalb der Klasse geändert werden dürfen und nur über Getter- und Setter-Funktionen zugänglich sind. Dies würde die zu definierende Klasse wie folgt ändern:
/ ** * Die Ghost-Klasse * / public class Ghost // Ghost gibt private Zeichenfolge color an; privater String-Name; private Boolean isEatable; private Vector-Richtung; private int Geschwindigkeit; / ** * Funktion - verschiebt den Ghost * / public void move () // Code, der den Geist in die aktuelle Richtung verschiebt / ** * Funktion - Geisterrichtung ändern * / private void changeDirection () // Code that ändert die Richtung des Ghosts / ** * Funktion - Ghost-Geschwindigkeit ändern * / private void changeSpeed () // Code, der die Ghost-Geschwindigkeit ändert / ** * Funktion - Ghost-Farbe ändern * / private void changeColor () // Code, der die Ghost-Farbe ändert / ** * Funktion - Ghost-Status ändern * / public void changeState () // Code, der den Ghost-Status ändert // Diese Funktion ruft auch die drei Funktionen changeDirection, changeSpeed und changeColor auf. / ** * Getter und Setter * /…
Encapsulation kann helfen, mehr wartbaren Code zu erstellen, indem die Auswirkungen von Codeänderungen verhindert werden. Es hilft auch bei der Erstellung von lose gekoppeltem Code, indem der direkte Zugriff auf den Status und das Verhalten eines Objekts reduziert wird.
Im nächsten Schnelltipp werden das Abstraktionsprinzip erläutert und wie mit diesem die Redundanz von Code reduziert werden kann. Folgen Sie uns auf Twitter, Facebook oder Google+, um über die neuesten Beiträge auf dem Laufenden zu bleiben.