virtual (C# リファレンス)
virtual キーワードは、メソッド、プロパティ、インデクサー、またはイベントの宣言を修飾し、派生クラスでオーバーライドできるようにするために使用します。 たとえば、このメソッドは、このメソッドを継承するクラスでオーバーライドできます。
public virtual double Area()
{
return x * y;
}
仮想メンバーの実装は、オーバーライドするメンバーによって派生クラスで変更できます。 virtual キーワードを使用する方法の詳細については、「Override キーワードと New キーワードによるバージョン管理 (C# プログラミング ガイド)」および「Override キーワードと New キーワードを使用する場合について (C# プログラミング ガイド)」を参照してください。
解説
仮想メンバーが呼び出されるときには、オブジェクトの実行時の型が、オーバーライドするメンバーで確認されます。 メンバーをオーバーライドしている派生クラスがない場合には、おそらくはオリジナルのメンバーである、最派生クラスでオーバーライドするメンバーが呼び出されます。
既定では、これらのメソッドは非仮想です。 非仮想メソッドのオーバーライドはできません。
virtual 修飾子は、static、abstract, private、または override の各修飾子と一緒には使用できません。 仮想プロパティの例を次に示します。
class MyBaseClass
{
// virtual auto-implemented property. Overrides can only
// provide specialized behavior if they implement get and set accessors.
public virtual string Name { get; set; }
// ordinary virtual property with backing field
private int num;
public virtual int Number
{
get { return num; }
set { num = value; }
}
}
class MyDerivedClass : MyBaseClass
{
private string name;
// Override auto-implemented property with ordinary property
// to provide specialized accessor behavior.
public override string Name
{
get
{
return name;
}
set
{
if (value != String.Empty)
{
name = value;
}
else
{
name = "Unknown";
}
}
}
}
仮想プロパティは抽象メソッドと同様に動作しますが、宣言の構文および呼び出しの構文に相違があります。
静的プロパティで virtual 修飾子を使用するのはエラーです。
継承された仮想プロパティを派生クラス内でオーバーライドできます。オーバーライドするには、override 修飾子を使用しているプロパティ宣言をインクルードします。
使用例
この例では、Dimensions クラスに 2 本の座標軸 x および y と、Area() 仮想メソッドがあります。 図形のクラス、たとえば Circle、Cylinder、および Sphere が Dimensions クラスを継承し、各図形について、表面積が計算されます。 各派生クラスには、Area() の独自のオーバーライド実装があります。 このプログラムは、メソッドと関連付けられているオブジェクトに従って、Area() の適切な実装を呼び出すことによって、各図形の適切な表面積の計算および表示を行います。
継承された Circle、Sphere、および Cylinder のすべてのクラスが、基本クラスを初期化するコンストラクターを使用することに注意してください。たとえば、次のようなコードです。
public Cylinder(double r, double h): base(r, h) {}
これは、C++ の初期化リストに似ています。
class TestClass
{
public class Dimensions
{
public const double PI = Math.PI;
protected double x, y;
public Dimensions()
{
}
public Dimensions(double x, double y)
{
this.x = x;
this.y = y;
}
public virtual double Area()
{
return x * y;
}
}
public class Circle : Dimensions
{
public Circle(double r) : base(r, 0)
{
}
public override double Area()
{
return PI * x * x;
}
}
class Sphere : Dimensions
{
public Sphere(double r) : base(r, 0)
{
}
public override double Area()
{
return 4 * PI * x * x;
}
}
class Cylinder : Dimensions
{
public Cylinder(double r, double h) : base(r, h)
{
}
public override double Area()
{
return 2 * PI * x * x + 2 * PI * x * y;
}
}
static void Main()
{
double r = 3.0, h = 5.0;
Dimensions c = new Circle(r);
Dimensions s = new Sphere(r);
Dimensions l = new Cylinder(r, h);
// Display results:
Console.WriteLine("Area of Circle = {0:F2}", c.Area());
Console.WriteLine("Area of Sphere = {0:F2}", s.Area());
Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
}
}
/*
Output:
Area of Circle = 28.27
Area of Sphere = 113.10
Area of Cylinder = 150.80
*/
C# 言語仕様
詳細については、「C# 言語仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。