C# 入門：オブジェクト指向

# はじめに
仕事でC#を使うことになりそうなので、Pythonの経験しかない私がC#の基本から学習していく過程をアウトプットしていこうと思います。
今回は、オブジェクト指向について学習したことをアウトプットします。

# 環境
- Windows10
- Visual Studio 2022

# オブジェクト指向とは
- オブジェクト = モノ
- メリット
    - きれいなコードがけける
    - 作業スピードが上がる
    - 人間が把握できるプログラムが実現できる

- プロパティとメソッドで成り立っている

「本」というクラスがあるとすると、以下のイメージになります。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610435/ad4ad304-b6dc-ed72-0797-e3d64a7a50a6.png)


# メソッド
VisualStudioのコンソールアプリケーション（.NETFramework）プロジェクトを開始するとデフォルトで生成されるProgram.csの中の、```static void Main()```の部分がメソッド
```cs
static void Main(string[] args)
{
}
```
- メソッドはプログラムに必ず1つ用意しないといけない
- Mainメソッドは必ず必要

### メソッドを作って呼び出してみる
新しいメソッド```Study```を作ってみます。
```cs
static void Study()
{
    //学習メソッド
    Console.WriteLine("C#を学習する");
}
```

Mainメソッドで```Study```メソッドを呼び出します。<br>
```メソッド名();```で呼び出します。
```cs:Program.cs
static void Main()
{
    //メインメソッド
    Study();
}
```

全体のソースは以下のようになります。
```cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PractisClass
{
    internal class Program
    {
        static void Main()
        {
            //メインメソッド
            Study();
        }
        static void Study()
        {
            //学習メソッド
            Console.WriteLine("C#を学習する");
        }
    }
}
```

# クラス
今回は以下のような勇者クラスを作成します。
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610435/43aab032-0e5c-e843-ba05-bcc5060dad14.png)
プロパティの部分が、
```cs
string name = "勇者";
int mp = 50;
```
メソッドは以下のようになります。
かっこで引数を受け取れ、メソッドの中で使えます。
```cs
void Attack()
{
    Console.WriteLine(name + "は攻撃した");
}
void Magic(int useMp)
{
    if (mp >= useMp) {
        Console.WriteLine(name + "は魔法を使った");
        mp -= useMp;
        Console.WriteLine("MPを" + useMp + "使って残りMPは" + mp);
    } else {
        Console.WriteLine(name + "はMPが足りず魔法を使えなかった");
    }
}
void Run()
{
    Console.WriteLine(name + "は逃げた");
}
```
呼び出すときは、かっこに引数をわたせます。
```cs
//メソッドを呼びだす
Attack();
int useMp = 5;
Magic(useMp);
Run();
```

全体は以下のようにな感じです。
```cs:Program.cs
using System;

namespace PractisClass
{
    internal class Hero
    {
        //勇者クラスのプロパティを定義する
        string name = "勇者";
        int mp = 50;

        static void Main()
        {
            //インスタンスオブジェクトを作る
            Hero hero = new Hero();
            //メソッドを呼びだす
            hero.Attack();
            int useMp = 5;
            hero.Magic(useMp);
            hero.Run();
        }
        void Attack()
        {
            Console.WriteLine(name + "は攻撃した");
        }
        void Magic(int useMp)
        {
            if (mp >= useMp) {
                Console.WriteLine(name + "は魔法を使った");
                mp -= useMp;
                Console.WriteLine("MPを" + useMp + "使って残りMPは" + mp);
            } else {
                Console.WriteLine(name + "はMPが足りず魔法を使えなかった");
            }
        }
        void Run()
        {
            Console.WriteLine(name + "は逃げた");
        }
    }
}
```
# インスタンス
インスタンスとは、クラスという設計図から作成された物体。
オブジェクト指向のなかでの立ち位置は、以下のようになります。
- <b>オブジェクト</b>：概念や物体をふんわり表現したもの
- <b>クラス</b>：モノの概念や設計図のようなもの
- <font color="Red"><b>インスタンス：クラスによって作成された物体</b></font>
「人間」クラスからインスタンスをnewしてみます。
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610435/d7ab943a-b3bf-f3da-3070-30c0dcc5968c.png)
```cs:Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PractisClass
{
    class Human
    {
        //--------------
        //属性
        //--------------
        //年齢
        private int age;
        //--------------
        //操作
        //--------------
        //年齢設定
        public void setAge(int age)
        {
            this.age = age;
        }
        //年齢取得
        public int getAge()
        {
            return this.age;
        }
    }
    internal class Program
    {
        static void Main(String[] args)
        {
            //Humanクラスのインスタンス「yamada」を生成
            Human yamada = new Human();
            //年齢を設定
            yamada.setAge(18);
            //年齢を表示
            Console.WriteLine("山田の年齢：" + yamada.getAge());
        }
        
    }
}
```
ポイントは、年齢の設定とコンソールへの表示はクラスのHumanに対しておこなっているわけではなく、Mainメソッドでnewしたインスタンスに対して行っている事です。

# コンストラクタ
クラスをnewした瞬間に実行される関数のこと。
インスタンスに情報を追加が事が出来ます。

勇者クラスがあったとすると、
名前、HP、MPをインスタンスが生成されたタイミングで渡すことができます。
今回は、プレイヤークラスをnewするときに名前を追加できるコンストラクタを作っていきます。
```cs:Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PractisClass
{

    internal class Program
    {
        static void Main(String[] args)
        {
            //newするときにかっこの中で名前を追加できる
            var player1 = new Player("勇者すずき");
            player1.Attack();
            var player2 = new Player("勇者たなか");
            player2.Attack();
            player1.Attack();
        }

    }
    public class Player
    {
        //newしたときに引数を受け取り、Playerクラスの名前を定義する
        private string name;
        public Player(string name)
        {
            this.name = name;
        }
        public void Attack()
        {
            Console.WriteLine(this.name + "はスライムに攻撃した");
        }
    }

}
```
出力
```terminal
勇者すずきはスライムに攻撃した
勇者たなかはスライムに攻撃した
勇者すずきはスライムに攻撃した
```


Playerクラスを定義した直後に
```cs
private string name;
public Player(string name)
{
    this.name = name;
}
```
と書くことで、
```cs
var player1 = new Player("勇者すずき")
```
のようにnewするときのかっこに名前を渡せばプロパティを追加出来ます。