[JAVA] Prise de conscience de l'orientation objet pendant six mois de programmation

introduction

Bonjour, c'est @ itti1021 en charge du MakeIT AdventCalendar2018 19 jours. Demain, @ yozakura121 publiera.

Pour faire une brève auto-introduction, j'ai commencé à étudier la programmation à partir de JavaScript il y a environ six mois, j'ai lu un livre d'introduction à Java et je me suis récemment intéressé à PHP. (Je veux affiner cette année)

Au début, je pensais écrire du code en Java, mais je n'avais ni le temps ni la confiance pour le rendre intéressant, alors j'ai arrêté. ~~ Je ne dis pas que cet article était intéressant. ~~

Alors qu'est-ce que tu fais? Je voudrais donc écrire ma perception actuelle de l'orientation des objets. Je l'ai écrit pour en faire un article, mais ce n'est que mon opinion personnelle pour le moment, alors soyez gentil.

Contenu

Tout d'abord, qu'est-ce que l'orientation objet?

L'orientation objet est le concept de composantisation utilisé dans le développement de systèmes. ** ** En d'autres termes, l'idée est de rendre le programme plus facile à comprendre pour les humains en divisant ou en remplaçant les choses qui existent réellement en parties appelées objets.

Il est fait pour imiter le monde réel, et lorsqu'il y a un changement dans le monde réel, les parties correspondantes sont modifiées ou remplacées. Cela réduira le temps que vous consacrez à la programmation et réduira les écarts dans le développement multijoueur.

Éléments de base dans l'orientation objet

Orienté objet a des éléments tels que des classes, des champs, des méthodes et des instances, et cette fois je vais aborder les quatre ci-dessus.

Une classe est un ensemble d'objets définis par le programmeur qui sont regroupés et reçoivent un nom unique, comme un ** dessin de conception ** facile à voir et à manipuler pour les humains. La classe a des champs et des méthodes décrits ci-dessous qui décrivent à quoi il ressemble et comment cela fonctionne pour le sujet. (Les champs et méthodes ont d'autres noms, mais cette fois ils sont omis.) Classe humaine, classe avion, classe takoyaki, etc.

-** Champ **

Décrivez ce que la classe a ** et ** caractéristiques **. Par exemple, dans la classe humaine, le champ oculaire, le champ nasal, le champ buccal, etc. seront définis.

-** Méthode **

Décrivez le ** mouvement ** et la ** réaction ** de cette classe. De même, s'il s'agit d'une classe humaine, définissez la méthode en cours d'exécution, la méthode de sommeil, la méthode de consommation, etc.

C'est une ** entité ** qui est réellement gérée dans la programmation générée à partir de la classe. Vous pouvez créer une instance humaine à partir de l'exemple de classe humaine.

Ce que vous voulez être orienté objet

Qu'est-ce que c'est (champ) Que peut-on faire (méthode) Moule (classe) Créer une entité (instance) en utilisant En déplaçant cela, ** le monde réel est reproduit dans le monde virtuel appelé programme **.

En fait un peu de code Java

Pour le moment, j'ai introduit tous les éléments, mais comme le texte seul est ennuyeux, je posterai le code Java qui correspond au contenu d'ici. (Les promesses détaillées telles que les erreurs de compilation et d'instanciation, ainsi que les spécifications du jeu ne seront pas prises en compte. De plus, elles seront omises le cas échéant.) ~~ C'est difficile d'écrire ~~ Veuillez me pardonner car cela s'écarte du sujet principal.

スライム

Tout le monde sait (?) C'est un monstre d'enseigne d'un jeu célèbre. Voici le code Java pour représenter le slime avec les quatre éléments ci-dessus.

Slime.java


//classe
public class Slime {
    //champ
    String name = "Vase"; // VaseA,VaseB,VaseC 名前を宣言
    int hp = 5; //Déclarer HP
    int mp = 0; //Déclarer MP

    //Méthode
    void attack(Hero heroInstance) {
        heroInstance.hp = hp - 1;
        System.out.println(heroInstance.name + "1 dommage!");
    }
    void run() {
        //En traitement
        System.out.println(this.name + "Haha a commencé à se mettre en colère!");
    }
}
//Instancier depuis l'appelant
Slime slimeInstance = new Slime();

La classe slime est désormais une instance de slime dans le monde virtuel.

Trois principales fonctions orientées objet

De plus, il existe un mécanisme pour faciliter la programmation orientée objet et réduire les erreurs. Ce sont ** [Dissimulation](# Hide-Encapsulation), [Inheritance](# Inheritance-Inheritance), [Polymorphism](# Polymorphism-Polymorphism) **.

Dissimulation (encapsulation)

C'est une fonction qui limite la lecture et l'écriture aux champs et à l'appel de méthodes. Même dans le monde réel, les choses difficiles à utiliser, comme le contenu des portefeuilles et des ordinateurs personnels, et les choses difficiles à voir sont gérées en les portant ou en les restreignant. Orienté objet signifie appliquer le ** contrôle d'accès ** à la classe.

Alors, que se passe-t-il si vous ne le cachez pas? Cela ressemble au code ci-dessous.

Hero.java


//Classe courageuse
public class Hero {
    String name = "Courageux"; //Déclaration de nom
    int hp = 100; //Déclaré un homme courageux de HP100
    int mp = 50; //Déclaration MP
    String state = default; //Aucune condition anormale
    //Abréviation

    void attack(Slime slimeInstance) {
        //Processus de combat
    }
    void run() {
        //En traitement
    }
    void useItem(Item itemInstance) {
        //Traitement utilisant des chiens
    }
    //Abréviation
}

Priest.java


//Classe de moine
public class Priest {
    String name = "Moine";
    int hp = 70;
    int mp = 100;
    String state = default;

    //Abréviation
    //Récupération complète des PV de Behoma Hero
    void healAll(Hero heroInstance) {
        if (this.mp > 9) {
            //Si votre MP est de 10 ou plus
            heroInstance.hp = -100;
            this.mp = this.mp - 10;
            System.out.println(heroInstance.name + "HP a complètement récupéré!");
        } else {
            System.out.println("Pas assez de MP!");
        }
    }
}

C'est le code pour créer un héros avec HP100 et utiliser Behoma (un sort pour récupérer complètement HP) sur ce héros. Cependant, si vous faites cela, les PV du héros seront de -100. C'est parce que j'ai fait une erreur de frappe avec la méthode healAll.

Priest.java


void healAll(Hero heroInstance) {
    heroInstance.hp = -100; // heroInstance.hp = 100;Erreur de frappe
}

Sans contrôle d'accès de cette manière, un état qui est impossible dans la réalité sera créé. Par conséquent, ajoutez d'abord un modificateur d'accès appelé private au champ afin qu'il ne puisse pas être géré de l'extérieur.

Hero.java


public class Hero {
    // int hp = 100;Ajouter à
    private int hp = 100;
}

Cependant, comme les méthodes externes telles que healthAll ne peuvent pas être utilisées telles quelles, la méthode ** getter ** qui transmet les informations de champ de la propre classe à d'autres classes et la valeur reçue de l'autre classe est transmise à la propre classe. Ajoutez une méthode ** setter ** pour refléter dans le champ.

Hero.java


public class Hero {
    //Déclaration HP
    private int hp = 100;
>
    //méthode getter
    public int getHp() {
        return this.hp; //Transmettez HP à l'appelant
    }
>
    //méthode setter
    public void setHp(int hp) {
        this.hp = hp; //Définir le HP reçu de l'appelant
    }

Cette méthode getter / setter a un modificateur d'accès appelé public afin que vous puissiez l'appeler de n'importe où. De plus, la classe Priest ne peut plus gérer directement les champs de la classe Hero, alors réécrivez la méthode healthAll.

Priest.java


public class Priest {
    void healAll(Hero heroInstance) {
        if (this.mp > 9) {
            // heroInstance.hp = -100;changement
            int putHp = -100
            heroInstance.setHp(putHp);
            this.mp = this.mp - 10;
            System.out.println(heroInstance.getName() + "HP a complètement récupéré!");
        } else {
            System.out.println("Pas assez de MP!");
        }
    }
//Courir
Hero heroInstance = new Hero(); //Instance courageuse
Priest priestInstance = new Priest(); //Instance de moine
priestInstance.healAll(heroInstance); //Utilisez Behoma comme un héros
System.out.println("HP: " + heroInstance.getHp());
//Résultat d'exécution
HP: -100

Le résultat de l'exécution n'a pas changé, mais j'ai pu le cacher pour le moment. Et à ce stade, il y a déjà deux avantages.

Priest.java


//Exemple de réécriture
public class Priest {
    void healAll(Hero heroInstance) {
        // heroInstance.hp = -100;changement
        heroInstance.currentHp = -100;
    }

Si vous avez une ou deux classes, ce serait difficile si vous deviez le faire dans un développement à grande échelle. Il peut être modifié par erreur à l'endroit où il fonctionne normalement, ou il peut induire des erreurs de frappe.

Résoudre le problème d'origine

Si vous le cachez simplement, vous pouvez définir -100 pour les HP du héros après tout, alors ajoutez un contrôle de validité à la méthode du setter à la fin.

Hero.java


public class Hero {
    setHp(int hp) {
        // this.hp =Changer de hp
        if (hp < 0 || hp > 100) { // 0 ~Autre que 100
            throw new IllegalArgumentException("La valeur sur le point d'être définie dans HP est anormale.");
        }
        this.hp = hp;
}

Exécutez maintenant le code ci-dessus.

//Courir
Hero heroInstance = new Hero(); //Instance courageuse
Priest priestInstance = new Priest(); //Instance de moine
priestInstance.healAll(heroInstance); //Utilisez Behoma comme un héros
System.out.println("HP: " + heroInstance.getHp());
//Instruction d'erreur de résultat d'exécution
"La valeur sur le point d'être définie dans HP est anormale."

Peu importe votre prudence, des erreurs se produiront. Cela signifie se préparer soigneusement et l'empêcher.

La dissimulation est importante pour créer une classe comme un ** objet (objet) ** qui ne peut pas être vu ou réécrit par l'extérieur, et la collecter dans un programme afin qu'elle n'entre pas en conflit avec la réalité.

Résumé de la dissimulation

Héritage

Comme son nom l'indique, c'est une fonction qui vous permet d'hériter des éléments que vous avez d'une classe à l'autre. Par exemple, disons que vous voulez créer une nouvelle bouillie à bulles contenant du poison provenant de la vase. Vais-je réécrire un cours depuis le début à un tel moment?

バブルスライム

Bubble slime a les mêmes champs et méthodes que le slime, et a un effet toxique sur les attaques. La différence est le contenu de l'attaque. Le slime à bulles est un slime (le slime à bulles est un type de slime) Dans cette relation is-a, l'orientation objet utilise l'héritage.

BubbleSlime.java


public class BubbleSlime extends Slime { //Hériter de la classe de slime
    private String name = "Boue à bulles";
    private int hp = 10; //Réinitialiser HP à 10

    public void attack (Hero heroInstance) {
        //Pièce endommagée
        heroInstance.setHp(heroInstance.getHp() - 1);
        System.out.println(heroInstance.getName() + "1 dommage!");
        //Jugement empoisonné
        boolean result = new java.util.Random().nextBoolean(); //Générer vrai ou faux
        if (result) {
            heroInstance.setState(poison); //Si le résultat est vrai, poison
            System.out.println(heroInstance.getName() + "A été paniqué!");            
        }
}

Après la déclaration de classe, écrivez extend class (la classe dont vous souhaitez hériter) et écrivez la différence par rapport à la classe héritière. C'est tout ce dont vous avez besoin.

//Courir
BubbleSlime bubbleSlimeInstance = new BubbleSlime(); //Instance de vase à bulles
bubbleSlimeInstance.run(); //Faites en sorte que le slime à bulles utilise la méthode d'exécution
//Résultat d'exécution
"Bubble slime a commencé à se développer!"

Puisqu'il hérite de la classe slime, vous pouvez utiliser la méthode run sans la définir dans la classe bubble slime. De cette façon ** la même partie peut être évitée ** et le code sera plus facile à lire.

En outre, l'utilisation de l'héritage présente un autre avantage. Supposons que vous vouliez changer la méthode d'exécution de la classe slime de "glissant!" À "glissant!".

Slime.java


public class Slime {
    run() {
        //En traitement
        System.out.println(this.name + "Était glissant!");
    }
}

Si vous créez une classe de slime à bulles à partir de zéro sans héritage, vous devrez modifier la classe de slime à bulles après avoir modifié la classe de slime. À mesure que ce nombre augmente à un ou deux, la quantité de description, d'oubli de corriger et d'erreurs de frappe augmentera, et je pense que cela deviendra ingérable lorsqu'il atteindra des dizaines ou des centaines. Si vous utilisez l'héritage, vous pouvez simplement modifier la classe d'origine et elle sera reflétée dans toutes les classes héritées.

Récapitulatif de l'héritage

C'est bien que la quantité de description soit réduite et que ce soit plus facile à gérer. Je l'aime particulièrement.

Polymorphisme

C'est une fonction pour capturer l'instance vaguement. ~~ C'est très difficile à verbaliser, donc en un mot, c'est comme ça. ~~

Considérons maintenant l'ancienne classe de classe slime. Slime est un ennemi, n'est-ce pas? Alors définissons la classe ennemie.

Enemy.java


public abstract class Enemy {
    private String name; //Déclarer un nom
    private int hp; //Déclarer HP
    private int mp; //Déclarer MP

    abstract public void attack(Hero heroInstance) {}
    abstract public void run() {}

Laissez la méthode d'attaque et exécutez la méthode vides car la description change en fonction du monstre hérité. Lorsque vous laissez la méthode vide, préfixez la déclaration de classe avec abstract pour en faire une classe abstraite. Une classe abstraite est une classe qui ne peut pas être instanciée (matérialisée). Même si vous émettez une méthode d'attaque (commande d'attaque), vous ne pouvez pas gérer un ennemi qui ne fait rien et ne donne même pas d'explication.

Et créez une nouvelle classe Drakey. bat.jpg

Bat.java


public class Bat extends Enemy { //Hériter de la classe ennemie
    private String name = "Drakey";
    private int hp = 10;
    private int mp = 3;

    public void attack (Hero heroInstance) {
        //Pièce endommagée
        heroInstance.setHp(heroInstance.getHp() - 3);
        System.out.println(heroInstance.getName() + "3 dégâts!");

}
    public void run() {
        //En traitement
        System.out.println(this.name + "Je me suis fâché!");
}

** Flux d'héritage ** Ça a été foiré, donc pour résumer

(Source d'héritage ← Destination d'héritage)

Vase Classe ennemie (classe abstraite qui ne peut pas être matérialisée)    ↑    Slime class    ↑ Classe BubbleSlime (vérification de poison ajoutée à la méthode d'attaque)

Drakey Classe ennemie (classe abstraite qui ne peut pas être matérialisée)    ↑    Bat class

Il est devenu.

Jusqu'ici, nous sommes prêts. Alors, que signifie vraiment être vague? Prenons l'exemple suivant.

Hero.java


public class Hero {
    public void attack(Slime slimeInstance) {
        slimeInstance.setHp(slimeInstance.getHp() - 5); //5 dégâts à la vase
    }
    public void attack(Bat batInstance) {
        batInstance.setHp(batInstance.getHp() - 5); //5 dégâts à Drakey
    }

Si vous prenez toutes les instances strictement, vous devez préparer chaque méthode en fonction de l'instance cible, comme la méthode d'attaque pour slime et la méthode d'attaque pour drakey.

Strictement parlant, le slime et le drakey sont des types différents, mais ce sont les mêmes monstres ennemis. Alors, traitons-le vaguement comme ** ennemi **.

(En Java, il est nécessaire de déclarer un type tel que int ou String quant au type de variable dont il s'agit. Fondamentalement, s'il s'agit d'une classe Slime, une instance est affectée au type Slime, et s'il s'agit d'une classe Bat, une instance est affectée au type Bat, mais elle est héritée du type de classe abstraite. Il est permis d'inclure des classes qui sont

//Courir
Enemy slimeInstance = new Slime(); //Instance de slime
Enemy batInstance = new Bat(); //Instance de Drakey

Hero.java


public class Hero {
    public attack(Enemy enemyInstance) {
        enemyInstance.sethp(enemyInstance.getHp() - 5); //5 dégâts aux ennemis
}

En créant ainsi des instances du même type Ennemi, il devient possible de les traiter toutes ensemble. Il est également efficace avec la méthode d'exécution des monstres ennemis.

//Courir
Enemy[] enemies = new Enemy[3]; //Ennemi qui est apparu
enemies[0] = new Slime(); //Vase
enemies[1] = new BubbleSlime(); //Boue à bulles
enemies[2] = new Bat(); //Drakey
for (Enemy enemyInstance : enemies) { //Mettez les ennemis qui apparaissent dans le type Ennemi un par un
    enemyInstance.run(); //Utilisez la méthode d'exécution de l'instance contenue dans le type Enemy
}
//Résultat d'exécution
"Le slime était glissant!"
"Bubble slime a glissé et s'est enfui!"
"Drakey est fou!"

L'appelant a obligé chaque monstre à utiliser la même méthode d'exécution, mais chaque monstre se comporte à sa manière. C'est une source de mot polymorphe qui peut produire de nombreux états à partir d'une seule commande.

Résumé du polymorphisme

~~ C'était difficile à verbaliser, peut-être ai-je plus de mérite? Je pense···. ~~

Résumé

** Merci d'avoir lu l'article jusqu'à présent. ** ** J'ai omis cette fois, mais il y a divers engagements ainsi que des mérites, donc si vous êtes intéressé, veuillez le vérifier. De plus, comme j'ai peu de connaissances et d'expérience, j'aimerais demander à Masakari s'il y a quelque chose dont je parle.

クロコダイン.jpg

☝️☝️☝️ Je suis sûr que demain c'est moi

Recommended Posts

Prise de conscience de l'orientation objet pendant six mois de programmation
Une liste de rawValues pour UITextContentType.
Écrivez ce que vous avez pensé après avoir utilisé mybatis pendant six mois
Une demi-année d'auto-apprentissage fait du SPA avec Rails + Nuxt.js, alors jetez un œil
Programmation orientée objet
[Pour les débutants en programmation] Qu'est-ce qu'une méthode?
Résumé des fonctionnalités simples de Bootstrap pour les débutants
Un mémo pour moi que l'orientation de l'objet est quelque chose
Une collection de questions simples pour les débutants Java
Terme de programmation orienté objet
J'ai créé une image Docker pour la version japonaise de SDAPS
Sortie d'une liste de paramètres cron pour tous les utilisateurs.
Introduction à la programmation pour les étudiants du Collège: création de canevas
Polymorphisme que même les débutants en orientation objet peuvent comprendre
Liste des instructions MySQL pour les débutants en programmation * Mémo personnel
J'ai essayé de développer une application web à partir d'un mois et demi d'histoire d'apprentissage de la programmation