C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

オーバーライドの使い方 /なと (17/05/16(Tue) 10:31) #84104
Re[1]: オーバーライドの使い方 /初級者 (17/05/16(Tue) 10:59) #84108
Re[1]: オーバーライドの使い方 /774RR (17/05/16(Tue) 10:57) #84107
Re[1]: オーバーライドの使い方 /furu (17/05/16(Tue) 10:55) #84106
Re[1]: オーバーライドの使い方 /Hongliang (17/05/16(Tue) 10:54) #84105
  └ Re[2]: オーバーライドの使い方 /なと (17/05/16(Tue) 11:05) #84109 解決済み


親記事 / ▼[ 84108 ] ▼[ 84107 ] ▼[ 84106 ] ▼[ 84105 ]
■84104 / 親階層)  オーバーライドの使い方
□投稿者/ なと (3回)-(2017/05/16(Tue) 10:31:41)

分類:[C#] 

C#のオーバーライドについて質問です。

AAAを継承するBBB、CCC、DDDがあり、派生クラスでMsg()メソッドが定義されていない場合は基底クラスAAAのMsg()メソッドを呼び出すようにしたいと思っています。
ところがAAA型の変数でMsg()を実行するとAAA.Msg()が実行されてしまうため、目的のBBB.Msg()、CCC.Msg()が実行されません。
たとえばlistに内包された全ての変数に対してMsg()を実行したい時には、想定される派生型すべてをチェックしてキャストした後Msg()を呼び出すことでとりあえず解決していますが、これからどんどん派生クラスが増えて行くことを考えるとキャスト忘れが起きそうなのでスマートではないように思いました。
もし良い書き方があれば御教示頂けないでしょうか。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace オーバーライドメソッド呼び出し
{
    class Program
    {
        private static List<AAA> list = new List<AAA>();
        static void Main(string[] args)
        {
            list.Add(new AAA());
            list.Add(new BBB());
            list.Add(new CCC());
            list.Add(new DDD());

            Console.WriteLine("全てAAA.Msgが実行されてしまう。");
            foreach (var item in list)
            {
                item.Msg();
            }

            Console.WriteLine("-----");
            Console.WriteLine("それぞれキャストすれば意図した通りに実行されるが…");
            foreach (var item in list)
            {
                if (item is BBB)
                    ((BBB)item).Msg();
                else if (item is CCC)
                    ((CCC)item).Msg();
                else
                    item.Msg();
            }

            Console.ReadLine();
        }
    }

    public class AAA
    {
        public void Msg()
        {
            Console.WriteLine("AAA");
        }
    }
    public class BBB : AAA
    {
        public new void Msg()
        {
            Console.WriteLine("BBB");
        }
    }
    public class CCC : AAA
    {
        public new void Msg()
        {
            Console.WriteLine("CCC");
        }
    }
    public class DDD : AAA
    {
        //DDD専用のMsgメソッドは無いのでAAA.Msg()を流用する。
    }
}


[ □ Tree ] 返信 編集キー/

▲[ 84104 ] / 返信無し
■84108 / 1階層)  Re[1]: オーバーライドの使い方
□投稿者/ 初級者 (1回)-(2017/05/16(Tue) 10:59:41)
newキーワードはオーバーライドで使うものではありません。(隠蔽などで調べてみてください)
オーバーライドするためには基底クラスのメソッドにvirtual をつけ、
派生クラスのメソッドにoverride をつけてみてください。

[ 親 84104 / □ Tree ] 返信 編集キー/

▲[ 84104 ] / 返信無し
■84107 / 1階層)  Re[1]: オーバーライドの使い方
□投稿者/ 774RR (526回)-(2017/05/16(Tue) 10:57:22)
virtual と override を調査してからレッツトライ!

[ 親 84104 / □ Tree ] 返信 編集キー/

▲[ 84104 ] / 返信無し
■84106 / 1階層)  Re[1]: オーバーライドの使い方
□投稿者/ furu (97回)-(2017/05/16(Tue) 10:55:56)
No84104 (なと さん) に返信

newだから、隠蔽になり、BBB.Msg()は実行されません。

virtual,overrideを使用してください。


    public class AAA
    {
        public virtual void Msg()
        {
            Console.WriteLine("AAA");
        }
    }
    public class BBB : AAA
    {
        public override void Msg()
        {
            Console.WriteLine("BBB");
        }
    }

[ 親 84104 / □ Tree ] 返信 編集キー/

▲[ 84104 ] / ▼[ 84109 ]
■84105 / 1階層)  Re[1]: オーバーライドの使い方
□投稿者/ Hongliang (543回)-(2017/05/16(Tue) 10:54:33)
オーバーライドは、基底クラスのメンバにvirtualキーワードを、
派生クラスのオーバーライドするメンバにoverrideキーワードを使用します。

newキーワードを使うと、オーバーライドではなく、隠蔽という動作を示します。

class BaseClass {
    public virtual void TestOverride() { Debug.Print("BaseClass.TestOverride"); }
    public void TestHide { Debug.Print("BaseClass.TestHide"); }
}
class DerivedClass {
    public override void TestOverride() { Debug.Print("DerivedClass.TestOverride"); }
    public new void TestHide() { Debug.Print("DerivedClass.TestHide"); }
}

void Test() {
    BaseClass a = new DerivedClass();

    // オーバーライドだとインスタンスの型のメソッドが呼ばれる
    a.TestOverride();  // DerivedClass.TestOverride

    // 隠蔽だと変数の型のメソッドが呼ばれる
    a.TestHide();      // BaseClass.TestHide
}

[ 親 84104 / □ Tree ] 返信 編集キー/

▲[ 84105 ] / 返信無し
■84109 / 2階層)  Re[2]: オーバーライドの使い方
□投稿者/ なと (4回)-(2017/05/16(Tue) 11:05:30)
無事動きました!
いままでnewで事足りていたので、オーバーライドはnewだと思っておりました。
newとoverrideの使い分けについて勉強したいと思います。
解決済み
[ 親 84104 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -