佐々木屋

技術的なことから趣味まで色々書きます

シャドウとオーバーライドの違い

VB.NETにはオーバーライドに似たような機能でシャドウがあります。但し、オーバーライドとシャドウは機能としては似ているかもしれませんが、使用される意味としては全くの別物です。初学者は混同しがちなので注意して下さい。

読んで字のごとくですが、シャドウされたメソッドは隠されます。隠されるというとアクセス出来ないと思うかもしれませんが、決してそういうわけではありません。まず、以下の例を考えます。

Public Class BaseClass
    Public Overridable Sub ShowMessage()
        Console.WriteLine("基底クラス")
    End Sub
End Class

Public Class SubClass1
    Inherits BaseClass
    Public Overrides Sub ShowMessage()
        Console.WriteLine("派生クラス1")
    End Sub
End Class

Public Class SubClass2
    Inherits BaseClass
    Public Shadows Sub ShowMessage()
        Console.WriteLine("派生クラス2")
    End Sub
End Class

まぁ、単純な継承したクラスです。但し、SubClass1は基底クラスのメソッドをオーバーライドしていますが、SubClass2はシャドウしています。シャドウはShadowsキーワードをプロシージャ名の前につけます。これはVB.NET特有のものです。

挙動にどのような影響があるのか、いつものごとく呼び出してみます。

Dim test1 As New SubClass1()
Dim test3 As New SubClass2()

test1.ShowMessage()
test3.ShowMessage()
派生クラス1
派生クラス2

あれ?何も変わりませんね。

では、基底クラスを型にして派生クラスを呼び出すように変更してみます。

Dim test2 As BaseClass = New SubClass1()
Dim test4 As BaseClass = New SubClass2()

test2.ShowMessage()
test4.ShowMessage()
派生クラス1
基底クラス

挙動が変わりました。

オーバーライドした場合は基底クラスを型にして派生クラスを呼び出しても変化しません(派生クラスのメソッドが呼ばれる)が、シャドウした場合は派生クラスのメソッドは隠されて基底クラスのメソッドが呼び出されます。つまり、シャドウは継承後メソッドをオーバーライドのように置き換えるわけではないということが分かります。

なお、シャドウは基底クラスのメソッドを仮想メソッドにしなくても使用可能です(基底クラスメソッド自体を書き換えるわけではない)。


C#の場合はnewキーワードを指定すると同じ動作になります。

public class BaseClass {
    public virtual void ShowMessage() {
        Console.WriteLine("基底クラス");
    }
}

public class SubClass1 : BaseClass {
    public override void ShowMessage() {
        Console.WriteLine("派生クラス1");
    }
}

public class SubClass2 : BaseClass {
    public new void ShowMessage() {
        Console.WriteLine("派生クラス2");
    }
}

SubClass1 test1 = new SubClass1();
BaseClass test2 = new SubClass1();
SubClass2 test3 = new SubClass2();
BaseClass test4 = new SubClass2();

test1.ShowMessage();
test2.ShowMessage();
test3.ShowMessage();
test4.ShowMessage();
派生クラス1
派生クラス1
派生クラス2
基底クラス