LoginSignup
13
7
お題は不問!Qiita Engineer Festa 2023で記事投稿!

オブジェクト指向のオーバーライドは「そんな、兄さん……!?」のほう

Last updated at Posted at 2023-06-16

メソッドのオーバーロード:

同じ名前で異なる引数のメソッドを複数定義する(できる)

メソッドのオーバーライド:

スーパークラスのメソッドをサブクラスが新たな実装で置き換える

「オーバーロードとオーバーライドの違いが覚えられません」

え~と、
そうですね~、……。

……。

いや、大丈夫大丈夫!
オーバーロードとオーバーライドの違い、そんなに真面目に覚える必要、ないから!

オーバーロードとオーバーライドはペアの概念ではないです。
「あ! ==演算子と.Equalsメソッド間違っちゃった 」
とかはあり得ても、
「あっ! 間違って、オーバーロードしようとしてたところでオーバーライドしちゃった! てへぺろ!」
ってことはまず発生しません。

(せいぜい検索するときのワードで、「あれ? なんだっけ?」ってときに、知ってたらベンリだったり、
人の話聞くときに、「んじゃここはオーバーロードでやる感じで」「ッス!」ってできるくらいです。)

「オブジェクト指向プログラミングでベンリに使える」ってところが共通項で、
あとは名前と見た目似てるからって一緒にされてないか?

だから、熱心に暗記しなくてもよくて、
「へー、そんなことあるんだね」ってふんわりおさえて置いたらいいんじゃないでしょうか。

おしまい。
ありがとうございました。

と言いたいところだけど、

でもな、……たまにこういう問題が出るから……。

基本情報技術者平成29年秋期 午前問7

問7
オブジェクト指向プログラミングにおける,多相性を実現するためのオーバーライドの説明はどれか。

  1. ア:オブジェクト内の詳細な仕様や構造を外部から隠蔽すること
  2. イ:スーパークラスで定義されたメソッドをサブクラスで再定義すること
  3. ウ:同一クラス内に,メソッド名が同一で,引数の型,個数,並び順が異なる複数のメソッドを定義すること
  4. エ:複数のクラスの共通する性質をまとめて,抽象化したクラスを作ること

引用元: 基本情報技術者試験ドットコム

応用情報技術者平成30年春期 午前問7

問7
オブジェクト指向プログラミングにおいて,同一クラス内に,メソッド名が同一であって,引数の型,個数又は並び順が異なる複数のメソッドを定義することを何と呼ぶか。

  1. ア:オーバーライド
  2. イ:オーバーロード
  3. ウ:カプセル化
  4. 4:汎化

引用元: 応用情報技術者試験ドットコム

というわけで、さらっと押さえておきましょう。

オーバーロード

わけのわからぬまま、急に戦う羽目になったとします。

主人公:「うっ、ここは……?」
(なんか強い敵)
突然現れたヒロイン:「今は説明してる場合じゃない」
主人公:「え?」
ヒロイン:「その計算機をもって。Add関数を呼んで。それが威力を決めるわ。戦って、早く!」
主人公:「……これはなんだ!? Add関数が複数あるぞ」
ヒロイン:「心配しなくていいわ。引数が違えばコンパイラが決めてくれるから。とにかく引数を入れて、撃って!」
主人公:「(ええい、ままよ)Add――引数は1と1!」
コンパイラ:「オーバーロード――成功。int型同士の足し算と認識しました」
(オーバーロード発生)
(強い敵、倒れる)
主人公:「は、はは、すごい……。使いたい関数が勝手に判断されるなんて……そんなの、人智を超えている!(オーバーロード)」

コード例

using System;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Add(5, 10)); // 整数のAddを呼び出し
        Console.WriteLine(Add(5.5, 10.5)); // 浮動小数点数のAddを呼び出し
    }

    // 整数の加算
    static int Add(int a, int b)
    {
        return a + b;
    }

    // 浮動小数点数の加算
    static double Add(double a, double b)
    {
        return a + b;
    }
}

オーバーロードの説明

いうほど人智は超えてないな……1

まあそれはさておき、オーバーロードはコンパイラくんがはからってくれる恩寵っていうか、「それしてもいいよ、こっちで区別しとくから」というベンリ仕様です。

メソッド名が同じでも、引数が違うと異なる動作をするメソッドとして定義することができます。
実装するときは、引数の型や個数など、違いが分かるようにしなければなりませんが、どっか違わなきゃいけないというのは「で、どれを呼べばいいんですか?」の違い判定のためです。
メソッドが実行されるまで戻り値はわからないから、引数でどっか見分けつくようにしなきゃなりません。どのメソッドを呼び出すべきかは引数で判断しています。

なお、JavaやC++とかだと、「型・個数・順番」が違うとオーバーロードしてくれますが、Pythonなどは引数の順番に基づくオーバーロードをサポートしていません。
だから、型とか個数とか順番とか、あんまり細かいことは覚えていなくてもいいです。

オーバーライド

自分と戦っている相手が、妙に自分と似たような技を使っている。

主人公:「食らえっ! Attack()」
謎の男:「こちらもだ。Attack()!」
主人公:「くっ、Guard()」
謎の男:「Guard()」
主人公:(おかしい、さっきから戦い方が似すぎている……引数も、引数の型も同じ……まるで同じ関数を実装しているかのようだ……)
主人公:(偶然にしてはあまりに似すぎている……)
謎の男:「勘づいたようだな」
主人公:「そんな、まさか……(同じクラスを継承した)兄さん?

コード例

using System;

public abstract class Father
{
    public virtual void Attack()
    {
    }

    public virtual void Guard()
    {
    }
}

public class ElderBrother : Father
{
    public override void Attack()
    {
        Console.WriteLine("Elder brother attacks");
    }

    public override void Guard()
    {
        Console.WriteLine("Elder brother guards");
    }
}

public class YoungerBrother : Father
{
    public override void Attack()
    {
        Console.WriteLine("Younger brother attacks");
    }

    public override void Guard()
    {
        Console.WriteLine("Younger brother guards");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Father elderBrother = new ElderBrother();
        Father youngerBrother = new YoungerBrother();

        elderBrother.Attack();  // Outputs "Elder brother attacks"
        elderBrother.Guard();   // Outputs "Elder brother guards"

        youngerBrother.Attack();  // Outputs "Younger brother attacks"
        youngerBrother.Guard();   // Outputs "Younger brother guards"
    }
}

説明

オーバーライドは、基底クラス(親クラス)で定義されたメソッドを派生クラス(子クラス)で再定義することを指します。
派生クラスでは、基底クラスのメソッドを再定義し、その動作をオーバーライドできます。
兄も、弟も、同じ父さんから教えを受けているので(クラスを継承しているので)、Attack()、Guard()を備えています。
出力は違いますが、引数の型も個数も一緒です(この場合0個なんですけれどもね)。

つまり……。

オーバーロードはコンパイラがよきにはからってくれるほう。
関数同士は同名なだけの他人です。

オーバーライドは「そんな、兄さん……!?」のほう。
親がいるほう。継承が起こる方。
よく似た戦いをするほう。
兄の精神が乗っ取られるほう(オーバーライド)。
しかもその兄さんは、
父さんと(引数の個数や数、順番)がうりふたつ。
なんでそっくりかっていうと
「息子よ、最低限俺を継承するからにはこの関数は備えとけよ」っていうのが父さんの教えだからです。

兄:ちなみにこのオーバーライドしたやつをオーバーロードもできてさ……

public class ElderBrother : Father
{
    public ElderBrother() : base(5)
    {
    }

    // メソッドオーバーロード: 引数なし
    public override void Attack()
    {
        Console.WriteLine("Elder brother attacks with power " + power);
    }

    // メソッドオーバーロード: 引数あり
    public void Attack(int extraPower)
    {
        Console.WriteLine("Elder brother attacks with extra power " + (power + extraPower));
    }

    public override void Guard()
    {
        Console.WriteLine("Elder brother guards");
    }
}

まあ、父さんの教えをむざむざやぶって独自流にAtackを実装するようなことをしているので良いことがないし、わざわざやらないならうっかりオーバーロードしたいのにオーバーライドしちゃったってことはないはずです。

  1. オーバーロード(overload)のload(荷物)は君主(lord)ではなく、カッコいい意味はないぞ!

13
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7