Petit conseil le principe d'encapsulation OOP

Nous avons discuté de la programmation orientée objet pour les développeurs de jeux en général et des principes spécifiques de la POO en matière de cohésion et de couplage. Voyons maintenant encapsulation et comment il aide à garder le code faiblement couplé et plus maintenable.


Remarque: Bien que cette astuce soit expliquée avec Java, vous devriez pouvoir utiliser les mêmes techniques et concepts dans presque tous les environnements de développement de jeux..


Qu'est-ce que l'encapsulation??

L'encapsulation est le principe de la dissimulation d'informations. C'est le la mise en oeuvre (le fonctionnement interne) d'un objet est caché du reste du programme.

Un exemple populaire d’encapsulation que vous entendrez est la conduite d’une voiture. Avez-vous besoin de savoir exactement comment chaque aspect d'une voiture fonctionne (moteur, carburateur, alternateur, etc.)? Non - vous devez savoir comment utiliser le volant, les freins, l'accélérateur, etc..

Un autre exemple est la recherche d'une valeur dans un tableau. En Java, vous pouvez effectuer les opérations suivantes:

 int myArray [] = 1, 2, 3, 5, 7, 9, 11, 13; Arrays.asList (myArray) .contains (11);

Le code ci-dessus retournera vrai si la valeur 11 est dans mon tableau, sinon il reviendra faux. Comment le contient () méthode de travail? Quelle technique de recherche utilise-t-il? Est-il pré-trier le tableau avant de chercher? La réponse est ça n'a pas d'importance parce que l'implémentation exacte de la méthode est cachée.


Pourquoi l'encapsulation est-elle utile??

L'encapsulation aide à créer du code qui est faiblement couplé. Les détails étant masqués, les autres objets ne sont plus en mesure de modifier directement l'état et le comportement d'un objet..

Cela aide aussi beaucoup lorsque vous devez changer le type de données d’une variable. Disons que vous avez décidé d'utiliser un Chaîne suivre le temps au format "hh: mm: ss". Au bout d’un moment, vous vous rendez compte qu’un int représenter les secondes pourrait être un meilleur type de données pour le temps. Non seulement vous devez changer le type de données dans l'objet, mais également chaque fois que vous avez référencé le temps de l'objet dans l'ensemble du programme!

Au lieu de cela, vous pouvez utiliser ce que l’on appelle les fonctions d’acquisition et de définition. Les accesseurs et les setters sont généralement de petites fonctions qui renvoient et définissent une variable, respectivement. Une fonction getter pour obtenir l'heure ressemblerait à ceci:

 public String getTime () heure de retour; 

Le getter va retourner un Chaîne valeur: la variable temps. Maintenant, quand on veut changer temps à un int, au lieu de changer tous les appels au getter, nous pouvons simplement changer la fonction de getter pour changer le int type de données dans un Chaîne Type de données.

 public String getTime () // divise l'heure en heures, minutes et secondes int hours = time / 3600; int reste = temps% 3600; int minutes = reste / 60; int secondes = reste% 60; // // combine le résultat en une chaîne séparée par des points et renvoyée heure + ":" + minutes + ":" + secondes; 
le % L'opérateur est appelé opérateur de module et renvoie le reste d'une division. Alors 10% 3 retournerais 1 puisque 10/3 = 3 avec un reste de 1.

La fonction getter renvoie maintenant un Chaîne et aucun des appels à la fonction ne doit changer. Le code est donc plus maintenable.


Comment appliquer ce principe

Astéroïdes

Revenons à l'exemple d'un navire tirant une balle introduite dans l'article d'accouplement. Rappelons que nous avons défini un navire comme suit:

 / ** * La classe de navire * / classe publique Navire / ** * Fonction - exécute le comportement (tâche) de retourner le navire * / public void rotation () // Code qui fait tourner le navire / ** * Fonction - exécute le comportement (tâche) de déplacer le navire * / public void move () // Code qui déplace le navire / ** * Function - exécute le comportement (tâche) de tirer avec le canon du navire * / public vide ( ) // Code qui fait que le navire tire une balle

Pour que le navire tire une balle, il suffit d'appeler ship.fire (). La manière dont le code implémente le tir d'une balle n'a pas d'importance, car tout ce qui nous intéresse est de tirer une balle. De cette façon, si vous voulez changer le code pour déclencher une explosion laser, il vous suffit de changer de méthode. Feu() et pas tous les appels à ship.fire ().

Cela vous permet de modifier n'importe quel aspect du fonctionnement du vaisseau sans avoir à changer la façon dont l'objet ship est utilisé partout ailleurs.

Tetris

Tetris a plusieurs façons de traiter les lignes de compensation. Encapsuler le comportement d'effacement d'une ligne vous permettra de changer rapidement la méthode que vous utilisez sans avoir à réécrire chaque utilisation de celle-ci. Cela vous permettra même de pouvoir modifier la méthode de la ligne claire pour créer différents modes de jeu dans le jeu..

Pac-Man

Une autre caractéristique de l’encapsulation consiste à masquer l’accès à un objet. Il arrive souvent que vous ne souhaitiez pas accéder de l'extérieur à l'état ou au comportement d'un objet et que vous souhaitiez le masquer à tout autre objet. Pour ce faire, vous pouvez utiliser des modificateurs de niveau d'accès qui donnent ou masquent l'accès aux états et comportements des objets..

Les modificateurs de niveau d'accès définissent deux niveaux d'accès:

  • Publique - n'importe quel objet peut accéder à tout moment à la variable ou à la fonction.
  • privé - seul l'objet contenant la variable ou la fonction peut y accéder.

(Il y a un troisième niveau - protégé - mais nous couvrirons cela dans un futur post.)

Rappelons qu'un fantôme avait les états suivants:

  • Couleur
  • prénom
  • Etat
  • direction
  • la vitesse

… Et a été défini comme suit:

 / ** * La classe Ghost * / classe publique Ghost / ** * Fonction - déplace le fantôme * / public void move () (// Code qui déplace le fantôme dans la direction actuelle / ** * Fonction - modifie le fantôme. direction * / public void changeDirection () // Code qui modifie la direction du Ghost / ** * Fonction - modifie la vitesse du Ghost * / public void changeSpeed ​​() // Code qui modifie la vitesse du Ghost / ** * Fonction - changez la couleur Ghost * / public void changeColor () // Code modifiant la couleur du Ghost / ** * Fonction - changez l'état du fantôme * / public void changeState () // Code modifiant l'état du Ghost // Cette fonction aussi appellera les trois fonctions de changeDirection (), changeSpeed ​​() et changeColor ()

Puisque changer de couleur(), changeSpeed ​​(), et changer de direction() sont des fonctions d’aide et ne sont pas censés être accessibles de partout ailleurs que dans la classe, nous pouvons les définir comme privé les fonctions. Tous les états du fantôme peuvent aussi être déclarés privé puisqu'ils ne devraient pas non plus être modifiés de l'extérieur de la classe, et uniquement accessibles via les fonctions getter et setter. Cela changerait la classe à définir comme suit:

 / ** * La classe Ghost * / Classe publique Ghost // Ghost déclare la couleur de chaîne privée; nom de chaîne privé; privé booléen isEatable; direction de vecteur privée; privé int vitesse; / ** * Fonction - déplace le fantôme * / public void move () // Code qui déplace le fantôme dans la direction actuelle / ** * Fonction - change le sens du fantôme * / private void changeDirection () // Code cela change la direction du fantôme / ** * Function - change la vitesse du fantôme * / private void changeSpeed ​​() // Code modifiant la vitesse du fantôme / ** * Function - change la couleur du fantôme * / private void changeColor () // Code qui modifie la couleur du fantôme / ** * Fonction - modifie l'état du fantôme * / public void changeState () // Code qui modifie l'état du fantôme // Cette fonction appellera également les trois fonctions changeDirection, changeSpeed ​​et changeColor / ** * Getters and setters * /…

Conclusion

L'encapsulation peut aider à créer davantage de code maintenable en empêchant l'effet d'entraînement des modifications de code. Il aide également à créer du code faiblement couplé en réduisant l'accès direct à l'état et au comportement d'un objet..

Dans le prochain conseil rapide, nous aborderons le principe de l'abstraction et comment il peut aider à réduire la redondance du code. Suivez-nous sur Twitter, Facebook ou Google+ pour vous tenir au courant des derniers messages..