プログラミングとかブログ

Unity/C#/SRPGStudio/RPGツクールMVの情報とかその他気になったことを調べて書きます。

warning CS0108 ○○ は継承メンバー ○○ を隠します。の意味

Unityで以下のような警告が出るときがあります。
warning CS0108: ○○' は継承メンバー '○○' を隠します。意図的に隠す場合はキーワード new を使用してください。
Assets/Scripts/InheritTestDerived.cs(16,21): warning CS0108:
`InheritTestDerived.Reset()' hides inherited member
`InheritTestBase.Reset()'. Use the new keyword if hiding was intended

f:id:shirakamisauto:20150504180950j:plain


警告なんで無視してもいいんですが、やっぱり気になります。
これはざっくり言うと、継承先の変数とか関数とかが継承元の同名のやつとダブってるけどそのままでいいの?という意味です。
継承がわからない人は継承 (C# によるプログラミング入門)を参照してください。


以下、下記のコードで詳しく説明します。

using UnityEngine;
using System.Collections;

    class InheritTestBase : MonoBehaviour
    {
        public void Reset()
        {
            Debug.Log("継承元!");
        }
    }

    class InheritTestDerived : InheritTestBase
    {
        void Reset()
        {
            Debug.Log("継承先!");
        }

        public void Start()
        {
            Reset();
        }
    }

 

実行すると以下のように継承先のメッセージが出力されます。

f:id:shirakamisauto:20150504205824j:plain

上記コードで、InheritTestDerived()はInheritTestBase()を継承しています。
継承しているので、InheritTestDerived()はInheritTestBase()のReset()を使用できます。

しかし、上記のコードではInheritTestDerived()にもReset()を記述しています。
この状態で「Reset();」とだけ記述した場合、InheritTestDerived()のResetなのかInheritTestBase()のResetなのか区別がつきません。
このときは上記のように継承先で新しく定義したほうのResetが実行されます。
継承元のResetは実行されず、実装上隠されることになります。

これをわかっててやってるなら問題はありません。
ただ、うっかり継承先に同名メソッドを記述して、継承元のやつが実行されないという不具合になる危険があります。
上記の例でいうと、「継承元!」と表示するつもりだったとしても、「継承先!」と表示されてしまうことになります。

こういうことを防ぐために、以下のようなnewキーワードが用意されています。

    new void Reset()
        {
            Debug.Log("継承先!");
        }

newキーワードによって意図的に隠していることが明示されます。
これにより、前述のうっかりミスを防ぐことができます。
そして、継承元のを使う気がないとコンパイラにアピールでき、警告を消すことができます。

ちなみに継承元のを使いたいという場合は、以下のようにbaseキーワードをつけると呼び出せます。

    public void Start()
        {
            base.Reset();
        }

 

実行すると以下のように継承元のメッセージが出力されます。

f:id:shirakamisauto:20150504205405j:plain