今日は脆弱な基底クラスの問題(fragile base class problem)について。
次のようなクラスがあったとします。
public class Parent
{
private int counter = 0;
public virtual void Increment1()
{
counter++;
Console.WriteLine("counter is " + counter.ToString());
}
public virtual void Increment2()
{
counter++;
Console.WriteLine("counter is " + counter.ToString());
}
}
このクラスを継承して新しいクラスを作ったとします。Increment2を次のようにオーバーライドしたとします。
public class Child : Parent
{
public override void Increment2()
{
Increment1();
}
}
このクラスを使用する次のようなプログラムが作成されました。
public static class Program
{
[STAThread]
public static void Main()
{
Child child = new Child();
child.Increment2();
Console.ReadLine();
}
}
この時点ではこのプログラムは特に問題なく動作します。
counter is 1
さて、この状態から、基底クラスの実装者は「中身が全く同じメソッドがあるため一方から他方を呼ぶようにコードを改良しよう」(実際は致命的な改悪なのだが)と考え、基底クラスを次のように変更しました。
public class Parent
{
private int counter = 0;
public virtual void Increment1()
{
Increment2();
}
public virtual void Increment2()
{
counter++;
Console.WriteLine("counter is " + counter.ToString());
}
}
この時点でプログラムは正常に動作しなくなります。派生クラスを実体化し、Increment1メソッドを呼び出した場合には、内部で派生クラスで再実装されたIncrement2メソッドが呼び出されます。派生クラスで再実装されたIncrement2メソッドは内部でIncrement1メソッドを呼び出します。メソッド呼び出しの無限ループです。スタックオーバーフローです。
Process is terminated due to StackOverflowException