[JAVA] Awareness of object-oriented programming for half a year

Introduction

Hello, it's @ itti1021 in charge of the MakeIT AdventCalendar2018 19 days. Tomorrow @ yozakura121 will post.

To give a brief self-introduction, I started studying programming from JavaScript about half a year ago, read an introductory book on Java, and recently became interested in PHP. (I want to narrow down this year)

At first, I was thinking of writing code in Java, but I didn't have the time and confidence to make it interesting, so I stopped. ~~ I'm not saying that this article was interesting. ~~

Then what are you doing? So I would like to write down my current perception of object orientation. I've written it to make it an article, but it's just my personal opinion at the moment, so it's easy.

Contents

-[First of all, what is object-oriented? ](#What is object-oriented first) -[Basic elements in object-oriented](#Basic elements in object-oriented) -[Three major object-oriented functions](#Three major object-oriented functions) -Hide -Inheritance -Polymorphism

First of all, what is object-oriented?

Object-oriented is the concept of componentization used in system development. ** ** In other words, the idea is to make the program easier for humans to understand by dividing or replacing things that actually exist into parts called objects.

It is made to imitate the real world, and when there is a change in the real world, the corresponding parts are modified or replaced. This will reduce the amount of time you spend on programming and reduce discrepancies in multiplayer development.

Basic elements in object orientation

Object-oriented has elements such as classes, fields, methods, and instances, and this time I will touch on the above four.

-** Class **

A class is a programmer-defined set of objects with a unique name, like a ** blueprint ** to make it easier for humans to see and handle. The class has fields and methods described below that describe what it looks like and how it works for the subject. (Fields and methods have other names, but they are omitted this time.) Human class, airplane class, takoyaki class, etc.

-** Field **

Describe what the class has ** and ** characteristics **. For example, in the human class, the eye field, nose field, mouth field, etc. will be set.

-** Method **

Describe the ** movement ** and ** reaction ** of that class. Similarly, if it is a human class, set the running method, sleeping method, eating method, etc.

It is the ** entity ** that is actually handled in the programming generated from the class. You can create a human instance from the example human class.

What you want to be object-oriented

What is it (field) What can you do (method) Mold (class) Create an entity (instance) using By moving this, ** the real world is reproduced in the virtual world called a program **.

Actually a little Java code

For the time being, I introduced all the elements, but since the sentences alone are boring, I will post the Java code that matches the content from here. (Detailed pledges such as compilation errors and instantiations, and game specifications will not be considered. Also, they will be omitted as appropriate.) ~~ It's hard to write ~~ Please forgive me because it deviates from the main subject.

スライム

Everyone knows (?) It is a signboard monster of a famous game. Here is the Java code to represent slime with the above four elements.

Slime.java


//class
public class Slime {
    //field
    String name = "Slime"; // SlimeA,SlimeB,SlimeC 名前を宣言
    int hp = 5; //Declare HP
    int mp = 0; //Declare MP

    //Method
    void attack(Hero heroInstance) {
        heroInstance.hp = hp - 1;
        System.out.println(heroInstance.name + "1 damage!");
    }
    void run() {
        //Processing
        System.out.println(this.name + "Haha started to get angry!");
    }
}
//Instantiate from caller
Slime slimeInstance = new Slime();

The slime class is now a slime instance in the virtual world.

Three major object-oriented functions

In addition, there is a mechanism to make object-oriented programming easier and reduce errors. They are ** concealment, inheritance, polymorphism **.

Concealment (encapsulation)

This function restricts reading and writing to fields and method calls. Even in the real world, things that are difficult to use, such as the contents of wallets and computers, and things that are difficult to see are managed by carrying around or limiting them. Object-oriented means applying ** access control ** to the class.

So what happens if you don't hide it? It looks like the following code.

Hero.java


//Brave class
public class Hero {
    String name = "Brave"; //Name declaration
    int hp = 100; //Declared a brave man of HP100
    int mp = 50; //MP Declaration
    String state = default; //No abnormal condition
    //Abbreviation

    void attack(Slime slimeInstance) {
        //Fighting process
    }
    void run() {
        //Processing
    }
    void useItem(Item itemInstance) {
        //Processing that uses dogs
    }
    //Abbreviation
}

Priest.java


//Monk class
public class Priest {
    String name = "Monk";
    int hp = 70;
    int mp = 100;
    String state = default;

    //Abbreviation
    //Full recovery of Behoma Hero's HP
    void healAll(Hero heroInstance) {
        if (this.mp > 9) {
            //If your MP is 10 or higher
            heroInstance.hp = -100;
            this.mp = this.mp - 10;
            System.out.println(heroInstance.name + "HP has fully recovered!");
        } else {
            System.out.println("Not enough MP!");
        }
    }
}

Code for creating a HP100 hero and using Behoma (a spell to fully recover HP) on that hero. However, if you do this, the hero's HP will be -100. This is because I made a typing mistake with the healAll method.

Priest.java


void healAll(Hero heroInstance) {
    heroInstance.hp = -100; // heroInstance.hp = 100;Typing mistake
}

Without access control in this way, a state that is impossible in reality can be created. Therefore, first add an access modifier called private to the field so that it cannot be handled from the outside.

Hero.java


public class Hero {
    // int hp = 100;Add to
    private int hp = 100;
}

However, since external methods such as healthAll cannot be used as it is, the ** getter ** method that passes the field information of the own class to other classes and the value received from the other class are passed to the own class. Add a ** setter ** method to reflect in the field.

Hero.java


public class Hero {
    //HP Declaration
    private int hp = 100;
>
    //getter method
    public int getHp() {
        return this.hp; //Pass HP to the caller
    }
>
    //setter method
    public void setHp(int hp) {
        this.hp = hp; //Set the HP received from the caller
    }

This getter / setter method has an access modifier called public, so it can be called from anywhere. Also, the Priest class can no longer handle the fields of the Hero class directly, so rewrite the healthAll method.

Priest.java


public class Priest {
    void healAll(Hero heroInstance) {
        if (this.mp > 9) {
            // heroInstance.hp = -100;change
            int putHp = -100
            heroInstance.setHp(putHp);
            this.mp = this.mp - 10;
            System.out.println(heroInstance.getName() + "HP has fully recovered!");
        } else {
            System.out.println("Not enough MP!");
        }
    }
//Run
Hero heroInstance = new Hero(); //Brave instance
Priest priestInstance = new Priest(); //Monk instance
priestInstance.healAll(heroInstance); //Use Behoma as a hero
System.out.println("HP: " + heroInstance.getHp());
//Execution result
HP: -100

The execution result has not changed, but I was able to hide it for the time being. And at this stage, there are already two benefits.

-** Read Only / Write Only fields can be realized ** Read Only (can be read externally but cannot be rewritten) unless the setter method is set Write Only (cannot be read though it can be rewritten from the outside) unless the getter method is set.

-** Information inside the class such as field names can be freely rewritten ** For example, suppose you want to change the field name HP that you have set this time to the field name currentHp (current HP). If you didn't prepare getter / setter method and read / write fields directly in an external class, you have to rewrite everything inside that class.

Priest.java


//Rewriting example
public class Priest {
    void healAll(Hero heroInstance) {
        // heroInstance.hp = -100;change
        heroInstance.currentHp = -100;
    }

If you have one or two classes, it would be difficult if you had to do this in a large-scale development. It may change the place where it works normally, or induce typing mistakes.

Solving the original problem

If you just hide it, you can set -100 to the hero's HP after all, so add a validity check to the setter method at the end.

Hero.java


public class Hero {
    setHp(int hp) {
        // this.hp =Change hp
        if (hp < 0 || hp > 100) { // 0 ~Other than 100
            throw new IllegalArgumentException("The value you are trying to set for HP is abnormal.");
        }
        this.hp = hp;
}

Now run the code above.

//Run
Hero heroInstance = new Hero(); //Brave instance
Priest priestInstance = new Priest(); //Monk instance
priestInstance.healAll(heroInstance); //Use Behoma as a hero
System.out.println("HP: " + heroInstance.getHp());
//Execution result error statement
"The value you are trying to set for HP is abnormal."

No matter how careful you are, mistakes will occur. It means preparing carefully and preventing it.

Concealment is important in order to create a class as one ** object (object) ** that cannot be seen or rewritten by the outside, and collect it into a program so that it does not conflict with reality.

Summary of concealment

--Can limit reading and writing --Easy to modify the inside of the class --Safe because the field cannot be handled directly from the outside

Inheritance

As the name suggests, it is a function that allows you to inherit the elements you have from class to class. For example, let's say you want to make a new bubble slime that has poison from slime. Will I write a class again from the beginning at such a time?

バブルスライム

Bubble slime has the same fields and methods as slime, and has a poisonous effect on attacks. The difference is the content of the attack. Bubble slime is slime (bubble slime is a type of slime). In this is-a relationship, object-oriented uses inheritance.

BubbleSlime.java


public class BubbleSlime extends Slime { //Inherit slime class
    private String name = "Bubble slime";
    private int hp = 10; //Reset HP to 10

    public void attack (Hero heroInstance) {
        //Damaged part
        heroInstance.setHp(heroInstance.getHp() - 1);
        System.out.println(heroInstance.getName() + "1 damage!");
        //Poison judgment
        boolean result = new java.util.Random().nextBoolean(); //Generate true or false
        if (result) {
            heroInstance.setState(poison); //If result is true, poison
            System.out.println(heroInstance.getName() + "Was freaked out!");            
        }
}

After the class declaration, write extends class (the class you want to inherit) and write the difference from the inheriting class. This is all you need.

//Run
BubbleSlime bubbleSlimeInstance = new BubbleSlime(); //Bubble slime instance
bubbleSlimeInstance.run(); //Have bubble slime use the run method
//Execution result
"Bubble slime has begun to grow!"

Since it inherits the slime class, you can use the run method without defining it in the bubble slime class. In this way ** the same part can be avoided ** and the code will be easier to read.

In addition, there is another benefit to using inheritance. Suppose you want to change the slime class run method from "sliding!" To "sliding!".

Slime.java


public class Slime {
    run() {
        //Processing
        System.out.println(this.name + "Was slippery!");
    }
}

If you are creating a bubble slime class from scratch without inheritance, you will have to modify the bubble slime class after modifying it. As this number increases to one or two, the amount of description, forgetting to correct, and typing mistakes will increase, and I think that it will become unmanageable when it reaches tens or hundreds. If you are using inheritance, you can simply modify the original class and it will be reflected in all inherited classes.

Summary of inheritance

--Code is easy to read and concise --You can reduce mistakes on the programmer side --Easy to identify the location where the error is corrected

It's good that the amount of description is reduced and it is easier to manage. I especially like it.

Polymorphism

It is a function to catch the instance vaguely. ~~ It's very difficult to verbalize, so in a word, it's like this. ~~

Now consider the former class of slime class. Slime is an enemy, isn't it? So we define an enemy class.

Enemy.java


public abstract class Enemy {
    private String name; //Declare a name
    private int hp; //Declare HP
    private int mp; //Declare MP

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

Leave the attack method and run method blank because the description changes depending on the inherited monster. When leaving the method blank, add abstract before the class declaration to make it an abstract class. An abstract class is a class that cannot be instantiated (materialized). Even if you issue an attack method (attack command), you can't handle an enemy that doesn't do anything and doesn't even give an explanation.

And create a new Drakey class. bat.jpg

Bat.java


public class Bat extends Enemy { //Inherit the enemy class
    private String name = "Drakey";
    private int hp = 10;
    private int mp = 3;

    public void attack (Hero heroInstance) {
        //Damaged part
        heroInstance.setHp(heroInstance.getHp() - 3);
        System.out.println(heroInstance.getName() + "3 damage!");

}
    public void run() {
        //Processing
        System.out.println(this.name + "I got angry!");
}

** Inheritance flow ** It's been messed up, so to summarize

(Inheritance source ← Inheritance destination)

Slime Enemy class (abstract class that cannot be materialized)    ↑    Slime class    ↑ BubbleSlime class (added poison check to attack method)

Drakey Enemy class (abstract class that cannot be materialized)    ↑    Bat class

It has become.

So far, we are ready. So what does it really mean to be ambiguous? Let's take the following as an example.

Hero.java


public class Hero {
    public void attack(Slime slimeInstance) {
        slimeInstance.setHp(slimeInstance.getHp() - 5); //5 damage to slime
    }
    public void attack(Bat batInstance) {
        batInstance.setHp(batInstance.getHp() - 5); //5 damage to Drakey
    }

If you take all the instances strictly, you have to prepare each method according to the target instance, such as attack method for slime and attack method for drakey.

Slime and Drakey are strictly different types, but they are the same enemy monster. So, let's treat it vaguely as an ** enemy **.

(In Java, it is necessary to declare a type such as int or String as to what kind of variable it is. Basically, if it is Slime class, the instance is assigned to Slime type, and if it is Bat class, the instance is assigned to Bat type, but it is inherited to the abstract class type. It is permissible to include classes that have been created.)

//Run
Enemy slimeInstance = new Slime(); //Slime instance
Enemy batInstance = new Bat(); //Drakey Instance

Hero.java


public class Hero {
    public attack(Enemy enemyInstance) {
        enemyInstance.sethp(enemyInstance.getHp() - 5); //5 damage to the enemy
}

By making instances of the same Enemy type in this way, it becomes possible to process them all together. It is also effective with the run method of enemy monsters.

//Run
Enemy[] enemies = new Enemy[3]; //Enemy that appeared
enemies[0] = new Slime(); //Slime
enemies[1] = new BubbleSlime(); //Bubble slime
enemies[2] = new Bat(); //Drakey
for (Enemy enemyInstance : enemies) { //Put the enemies that appeared into the Enemy type one by one
    enemyInstance.run(); //Use the run method of the instance contained in the Enemy type
}
//Execution result
"The slime was slippery!"
"Bubble slime slipped and sank!"
"Drakey is crazy!"

The caller made every monster use the same run method, but each monster behaves in its own way. It is a polymorphic etymology that can produce many states from one command.

Summary of polymorphism

--Strictly speaking, different instances can be processed together --Individual instances behave according to the definition in each class

~~ It was difficult to verbalize, maybe I have more merits? I think···. ~~

Summary

** Thank you for reading the article so far. ** ** I omitted this time, but there are various pledges as well as merits, so if you are interested, please check it out. Also, since I have little knowledge and experience, I would like to ask Masakari if there is anything I'm talking about.

クロコダイン.jpg

☝️☝️☝️ I'm sure tomorrow's me

Recommended Posts

Awareness of object-oriented programming for half a year
What I pointed out as a reviewer for half a year
A list of rawValues for UITextContentType.
Write what you thought after using mybatis for half a year
I made a SPA with Rails + Nuxt.js for half a year of self-study, so please take a look.
Object-oriented programming
[For programming beginners] What is a method?
What was good for a fledgling engineer who started programming for a year and a half, and what I thought I should have done
A brief summary of Bootstrap features for beginners
A memo for myself that object-oriented is something
A collection of simple questions for Java beginners
Object-oriented programming terminology
I made a Docker image of SDAPS for Japanese
Output a list of cron settings for all users.
Introduction to Programming for College Students: Making a Canvas
Polymorphism that even beginners of object-oriented programming can understand
List of MySQL sentences for programming beginners * Personal memo
I tried to develop a web application from a month and a half of programming learning history