勇者を育てて学ぶC#オブジェクト指向入門

広告

オブジェクト指向という言葉は少し難しそうですが、最初から用語を暗記する必要はありません。

今回は、ゲームの勇者を少しずつ育てながら、クラス、インスタンス、フィールドとプロパティ、メソッド、そしてカプセル化の入口までを体験します。

コードはすべて短くしてあります。上から読むだけでなく、C#のコンソールアプリに貼り付けて実行し、「表示がどう変わったか」を確かめながら進めてみてください。

このチュートリアルで作るもの

名前とHPを持ち、ダメージを受けたり回復したりできるゲームキャラクターを作ります。

  • クラス:キャラクターの仕組みをまとめる
  • インスタンス:実際に動かすキャラクターを作る
  • フィールド/プロパティ:名前やHPを持たせる
  • メソッド:攻撃を受ける、回復する動きを作る
  • カプセル化:HPを安全に変更できるようにする

完成形を一度に書くのではなく、1つ追加するたびに実行します。変化が見えたら、そのステップは成功です。

設計図から勇者とスライムのインスタンスが生まれるイラスト

ステップ1:クラスから勇者を1人作る

まずは、キャラクターの仕組みを表す Character クラスを作ります。そして、new Character() で実際の勇者を1人誕生させます。

var hero = new Character();

Console.WriteLine(hero.GetType().Name);

class Character
{
}

実行結果

Character

class Character はキャラクターの仕組みを決める部分です。そこから作った heroインスタンスです。

よく「クラスは設計図、インスタンスは設計図から作った実物」と説明されます。ここでは、Characterという仕組みからheroという登場人物を作ったと考えれば十分です。

ステップ2:名前とHPを持たせる

次は、勇者に名前とHPを持たせます。まずは仕組みが見えやすいように、単純なフィールドを使います。

var hero = new Character();

hero.Name = "ミント";
hero.Hp = 100;

Console.WriteLine(hero.Name + "のHPは" + hero.Hp);

class Character
{
    public string Name = "";
    public int Hp;
}

実行結果

ミントのHPは100

NameHp は、キャラクターが持つデータです。このようにクラスの中に直接用意した変数をフィールドと呼びます。

実行前に hero.Hp = 30; に変えてみてください。表示も30に変われば、クラスの中のデータを操作できています。

ステップ3:2人目を作るとインスタンスが分かる

別々のHPを持つ勇者とスライムのイラスト

同じ Character クラスから、勇者とスライムを作ってみます。

var hero = new Character();
hero.Name = "ミント";
hero.Hp = 100;

var slime = new Character();
slime.Name = "ぷるるん";
slime.Hp = 20;

Console.WriteLine(hero.Name + "のHPは" + hero.Hp);
Console.WriteLine(slime.Name + "のHPは" + slime.Hp);

class Character
{
    public string Name = "";
    public int Hp;
}

実行結果

ミントのHPは100
ぷるるんのHPは20

heroslime は、同じクラスから作られました。それでも名前とHPは別々です。

これが、1つのクラスから複数のインスタンスを作れるという感覚です。ゲームで同じ仕組みを使って、たくさんのキャラクターを登場させられる理由でもあります。

ステップ4:メソッドでダメージを受ける

データだけでなく、キャラクターらしい動きも持たせましょう。クラスの中に処理をまとめたものをメソッドと呼びます。

ここではフィールドをプロパティに書き換え、TakeDamage メソッドを追加します。

var hero = new Character();
hero.Name = "ミント";

Console.WriteLine("戦闘前:" + hero.Hp);
hero.TakeDamage(30);
Console.WriteLine("戦闘後:" + hero.Hp);

class Character
{
    public string Name { get; set; } = "";
    public int Hp { get; set; } = 100;

    public void TakeDamage(int damage)
    {
        Hp -= damage;
        Console.WriteLine(Name + "は" + damage + "ダメージ!");
    }
}

実行結果

戦闘前:100
ミントは30ダメージ!
戦闘後:70

NameHp は、今度はプロパティです。get で値を読み、set で値を変更できます。

TakeDamage(30)TakeDamage(5) に変えて再実行してみましょう。HPが95になれば、渡した数字によってメソッドの動きが変わることを確認できます。

ステップ5:HPを守るのがカプセル化の入口

HPをカプセルの中で安全に守るカプセル化のイラスト

今のコードでは、外から hero.Hp = -999; のような不自然な変更もできてしまいます。

そこで、HPの変更をクラス自身に任せます。private set を付けると、外からはHPを読めますが、自由には書き換えられなくなります。

var hero = new Character();
hero.Name = "ミント";

hero.TakeDamage(120);
hero.Heal(30);

Console.WriteLine("現在のHP:" + hero.Hp);

class Character
{
    public string Name { get; set; } = "";
    public int Hp { get; private set; } = 100;

    public void TakeDamage(int damage)
    {
        if (damage <= 0) return;

        Hp = Math.Max(0, Hp - damage);
        Console.WriteLine(Name + "は" + damage + "ダメージ!");
    }

    public void Heal(int amount)
    {
        if (amount <= 0) return;

        Hp += amount;
        Console.WriteLine(Name + "は" + amount + "回復!");
    }
}

実行結果

ミントは120ダメージ!
ミントは30回復!
現在のHP:30

120ダメージを受けても、Math.Max によってHPは0より小さくなりません。そのあと30回復して、HPは30になります。

データをむき出しにせず、安全な操作を通して変更する。これがカプセル化の大切な入口です。

ミニ挑戦:自分だけのキャラクターにしよう

ここまで動いたら、次のどれか1つを試してみてください。

  • 名前を自分の好きなキャラクター名に変える
  • AttackPower プロパティを追加して表示する
  • 回復後のHPが100を超えないようにする
  • スライムにも TakeDamage を使ってみる

たとえば、回復の上限を100にするなら、Hp += amount; を次の1行に置き換えます。

Hp = Math.Min(100, Hp + amount);

コードを少し変えて実行結果を予想し、実際に確かめる。この小さな繰り返しが、オブジェクト指向を自分のものにする近道です。

ここまでで体験したこと

  • クラスは、データと処理をまとめた仕組み
  • インスタンスは、クラスから作った実際の登場人物
  • フィールド/プロパティは、名前やHPなどのデータ
  • メソッドは、ダメージや回復などの動き
  • カプセル化は、データを安全な操作の内側に守る考え方

オブジェクト指向は、難しい用語を覚える競技ではありません。キャラクターのような「ひとまとまりの部品」を作り、その部品同士を組み合わせてプログラムを育てていく考え方です。

まずは今回の勇者に、攻撃力やレベル、自己紹介メソッドを追加して遊んでみてください。自分で変えたコードの結果が画面に出た瞬間から、オブジェクト指向はぐっと身近になります。

訪問数 6 回, 今日の訪問数 6回

広告