کلمه کلیدی virtual برای اصلاح متد، پراپرتی، شاخصگر یا اعلان رویداد استفاده می شود و به آنها اجازه می دهد که در کلاس مشتق شده رونویسی (override) شوند. برای مثال، این متد می تواند توسط هر کلاسی که از آن ارث بری می کند، رونویسی شود.
public virtual double Area()
{
return x * y;
}
پیاده سازی یک عضو مجازی (virtual) را می توان توسط عضو رونویسی کننده در یک کلاس مشتق شده، عوض کرد.
ملاحظات
وقتی یک متد مجازی فراخوانی می شود، نوع زمان-اجرای آن شیئ برای عضو رونویسی کننده بررسی می شود. عضو رونویسی کننده، در کلاس مشتق شده فراخوانی می شود، که ممکن است همان عضو اصلی باشد (اگر هیچ کلاس مشتق شده ای، آن عضو را رو نویسی نکرده باشد).
بطور پیش فرض، متدها غیر-مجازی هستند. شما نمی توانید متد غیر مجازی را رونویسی کنید.
شما نمی توانید از اصلاحگر 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";
}
}
}
}
متدهای مجازی مانند متدهای چکیده (abstract) رفتار می کنند، به استثناء تفاتهایی که در املاء اعلان و احضار آنها وجود دارد.
- استفاده از اصلاحگر virtual روی یک پراپرتی static خطا محسوب می شود.
- یک پراپرتی ارث بری شده ی مجازی، می تواند با ضمیمه کردن یک اعلان پراپرتی که از اصلاحگر override استفاده می کند، در یک کلاس مشتق شده رونویسی شود.
مثال
در این مثال، کلاس Dimensions حاوی دو مختصات x و y و متد مجازی()Area می باشد. کلاس شکل های مختلف از جمله دایره (Circle)، سیلندر (Cylinder) و کره (Sphere) از کلاس Dimensions ارث بری می کنند و مساحت سطح برای هر کدام از اشکال محاسبه می شود. هر کدام از کلاس های مشتق شده، پیاده سازی مخصوص به خود را برای متد Area() دارند. برنامه مطابق شیئی که به متد()Area پیوست شده ، با احضار کردن پیاده سازی مناسب از()Area مساحت مناسب را برای هر شکل محاسبه و نمایش می دهد.
توجه کنید که کلاس های ارث بری شده Circle ، Sphere و Cylinder همه از سازنده هایی (Constructor) که کلاس پایه را مقداردهی اولیه می کنند، استفاده می کنند، برای مثال:
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
*/