オブジェクト指向には、なぜいろいろな例えが出てくるの?

広告

オブジェクト指向を勉強していると、ゲームキャラクター、設計図と実物、銀行口座、車とエンジン、動物・犬・猫など、さまざまな例えが登場します。

初学者の方は、「結局、どの例えが正しいの?」と迷うかもしれません。

結論から言うと、どれか1つだけが正しいわけではありません。

例えごとに、説明するのが得意な部分が違います。オブジェクト指向には複数の考え方が含まれているため、学ぶ内容に合わせて例えを使い分けているのです。

オブジェクト指向は1つの考えだけではない

オブジェクト指向には、次のような考え方があります。

  • データと処理をまとめる
  • クラスからインスタンスを作る
  • 中のデータを勝手に変更させない
  • 部品を組み合わせる
  • 共通する特徴を受け継ぐ
  • 同じ命令でも、対象によって違う動きをさせる

これらを最初から全部まとめて説明すると、抽象的で分かりにくくなります。

そこで、説明したい内容ごとに、一番分かりやすい例えを使うわけです。

ゲームキャラクターは「データと処理をまとめる」例

まずは、ゲームのキャラクターを考えてみましょう。

キャラクターは、名前、HP、攻撃力などのデータを持っています。そして、攻撃する、回復する、ダメージを受けるといった処理も持っています。

class Character
{
    public string Name;
    public int Hp;

    public void Attack()
    {
        Console.WriteLine($"{Name}が攻撃した!");
    }
}

NameHpがデータ、Attack()が処理です。

ゲームキャラクターの例は、「あるものが持つデータと、そのデータを扱う処理をひとまとめにする」という感覚をつかむのに向いています。

設計図と実物は「クラスとインスタンス」の例

次は、設計図と実物という例えです。

自動車の設計図は、自動車そのものではありません。しかし、その設計図をもとに、実際の自動車を何台も作ることができます。

class Car
{
}

var car1 = new Car();
var car2 = new Car();

設計図にあたるものがクラス、そこから作られた実物がインスタンスです。

この例は、1つのクラスから複数のインスタンスを作れることを説明するのに向いています。

銀行口座は「カプセル化」の例

では、設計図の例だけで全部を説明できるでしょうか。

たとえば、銀行口座の残高をプログラムのどこからでも自由に書き換えられると困ります。本来は、「入金する」「出金する」という決められた手続きを通して変更したいはずです。

class BankAccount
{
    public int Balance { get; private set; }

    public void Deposit(int amount)
    {
        if (amount > 0)
        {
            Balance += amount;
        }
    }
}

この例では、残高を外から直接変更できないようにし、Deposit()を通して入金します。

このように、内部のデータを守り、決められた操作を通して扱う考え方をカプセル化と呼びます。

車とエンジンは「合成」の例

車はエンジンを持っています。これは、「車はエンジンである」ではなく、「車はエンジンを持つ」という関係です。

class Engine
{
    public void Start()
    {
        Console.WriteLine("エンジンを始動します");
    }
}

class Car
{
    private Engine engine = new Engine();

    public void Start()
    {
        engine.Start();
    }
}

このように、必要な部品を持たせて組み立てる考え方を合成、またはコンポジションと呼びます。

車とエンジンの例は、has-a(持っている)関係を説明するのに向いています。

動物・犬・猫は「継承とポリモーフィズム」の例

犬と猫には、「動物である」という共通点があります。その一方で、鳴き方は違います。

abstract class Animal
{
    public abstract void Speak();
}

class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("ワン");
    }
}

class Cat : Animal
{
    public override void Speak()
    {
        Console.WriteLine("ニャー");
    }
}

DogCatは、どちらもAnimalとして扱えます。

Animal[] animals =
{
    new Dog(),
    new Cat()
};

foreach (var animal in animals)
{
    animal.Speak();
}

同じSpeak()を呼び出しても、犬なら「ワン」、猫なら「ニャー」と動きが変わります。

共通する特徴を受け継ぐのが継承、同じ呼び出しで対象ごとに違う動きをするのがポリモーフィズムです。

なぜ1つの例えだけでは足りないのか

「設計図と実物」は、クラスとインスタンスの説明には分かりやすい例です。

しかし、その例だけでカプセル化やポリモーフィズムまで説明しようとすると、だんだん無理が出てきます。

反対に、銀行口座はカプセル化を説明しやすい一方で、クラスから複数のインスタンスを作る感覚を最初に伝えるには、設計図ほど直感的ではありません。

つまり、例えが多いのは教え方が定まっていないからではなく、オブジェクト指向を違う角度から見るためです。

例えは抽象的な世界へ渡るための橋

初学者にとって、変数は比較的イメージしやすいものです。

var price = 1000;

しかし、次のコードでは一度に考えることが増えます。

var account = new BankAccount();
  • BankAccountとは何か
  • accountとは何か
  • newは何をしているのか
  • なぜクラスを作るのか

そこで、いったん現実世界のものに置き換えます。

例えはオブジェクト指向そのものではありません。抽象的なプログラムの世界へ渡るための橋です。

例えを学ぶときの見方

例えが出てきたら、例えそのものを覚えるのではなく、「この例えでは何を説明しているのか」を考えてみましょう。

  • ゲームキャラクター → データと処理をまとめる
  • 設計図と実物 → クラスとインスタンス
  • 銀行口座 → カプセル化
  • 車とエンジン → 合成、has-a関係
  • 動物・犬・猫 → 継承、ポリモーフィズム

この対応を意識すると、例えが変わっても、学んでいる中心を見失いにくくなります。

まとめ

オブジェクト指向にさまざまな例えが登場するのは、1つの例えだけでは全体を説明しにくいからです。

それぞれの例えは、オブジェクト指向の別の部分を分かりやすくするために使われています。

そして最後には、例えから離れて次の考えに戻ることが大切です。

オブジェクト指向とは、プログラムを「データと、そのデータを扱う処理を持った部品」として組み立てていく考え方です。

例えは入口です。例えそのものが目的ではありません。

「今、この例えでは何を説明しようとしているのだろう?」と考えながら読むと、オブジェクト指向を整理しやすくなります。

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

広告

C#,入門

Posted by hidepon