في لغة C#، يمكن تعريف تسلسل هرمي من الأصناف باستخدام الوراثة، وهي تسمح للصنف المشتق (Car) بأن يرث سلوك الصنف الأصل (Vehicle) وبياناته. وإذا لم يُحدَّد صنف أصل، فإن الصنف يرث من الصنف object.
يمكن للأصناف الأصل أن توفّر وظائف للأصناف المشتقة بثلاثة أساليب:
virtual، وهي مثل الطريقة العادية، لكن الأصناف المشتقة يمكنها تغييرها.abstract، وهي طريقة بلا تطبيق و_يجب_ على الأصناف المشتقة تطبيقها. والصنف الذي يحتوي على طرق abstract يجب أن يُوسم بـ abstract أيضًا. ولا يمكن إنشاء كائنات من الأصناف المجرّدة.يسمح معدِّل الوصول protected بالوصول إلى عضو من أعضاء الصنف الأصل داخل الصنف المشتق، لكنه يمنع الوصول إليه من الأصناف الأخرى.
وتستطيع الأصناف المشتقة الوصول إلى أعضاء الصنف الأصل عبر الكلمة المفتاحية base.
// Inherits from the 'object' class
abstract class Vehicle
{
// Can be overridden
public virtual void Drive()
{
}
// Must be overridden
protected abstract int Speed();
}
class Car : Vehicle
{
public override void Drive()
{
// Override virtual method
// Call parent implementation
base.Drive();
}
protected override int Speed()
{
// Implement abstract method
}
}
مُنشئ الصنف المشتق يستدعي تلقائيًا مُنشئ الصنف الأصل قبل تنفيذ منطق مُنشئه الخاص. ويمكن تمرير الوسائط إلى مُنشئ الصنف الأصل باستخدام الكلمة المفتاحية base:
abstract class Vehicle
{
protected Vehicle(int wheels)
{
Console.WriteLine("Called first");
}
}
class Car : Vehicle
{
public Car() : base(4)
{
Console.WriteLine("Called second");
}
}
وعندما يُشتق أكثر من صنف من صنف أصل، فغالبًا ما تطبّق هذه الأصناف (الاثنان أو أكثر) إصدارات مختلفة من طريقة في الصنف الأصل. وهذا مبدأ مهم جدًا يُسمى تعدد الأشكال. وعلى سبيل المثال، في تنويع على المثال السابق نعرض كيف يمكن للكود الذي يستخدم Vehicle أن يغيّر سلوكه حسب نوع المركبة التي أُنشئ منها كائن.
abstract class Vehicle
{
public abstract string GetDescription();
}
class Car : Vehicle
{
public Car()
{
}
public override string GetDescription()
{
return "Runabout";
}
}
class Rig : Vehicle
{
public Rig()
{
}
public override string GetDescription()
{
return "Big Rig";
}
}
Vehicle v1 = new Car();
Vehicle v2 = new Rig();
v1.GetDescription();
// => Runabout
v2.GetDescription();
// => Big Rig
في هذا التمرين، تلعب لعبة تقمّص أدوار تُسمّى "Wizard and Warriors"، تتيح لك أن تلعب إما بشخصية Wizard أو بشخصية Warrior.
توجد قواعد مختلفة لكل من Warrior وWizard تحدد مقدار نقاط الضرر التي يسببها كل منهما.
وهذه هي القواعد بالنسبة إلى Warrior:
وهذه هي القواعد بالنسبة إلى Wizard:
Wizard تعويذة مسبقًابشكل عام، لا تكون الشخصيات عرضة للضرر أبدًا. لكن شخصيات Wizard تكون عرضة للضرر إذا لم تجهّز تعويذة.
لديك ستّ مهام تتعامل مع شخصيات Warrior وWizard.
أعد تعريف طريقة ToString() في صنف Character بحيث تُرجع وصفًا للشخصية بالصيغة "Character is a <CHARACTER_TYPE>".
var warrior = new Warrior();
warrior.ToString();
// => "Character is a Warrior"
تأكد من أن طريقة Character.Vulnerable() تُرجع دائمًا false.
var warrior = new Warrior();
warrior.Vulnerable();
// => false
Wizard بتجهيز تعويذةنفّذ طريقة Wizard.PrepareSpell() لتتيح لشخصية Wizard تجهيز تعويذة مسبقًا.
var wizard = new Wizard();
wizard.PrepareSpell();
Wizard عرضة للضرر عندما لا تجهّز تعويذةتأكد من أن طريقة Vulnerable() تُرجع true إذا لم يجهّز Wizard تعويذة، وتُرجع false بخلاف ذلك.
var wizard = new Wizard();
wizard.Vulnerable();
// => true
Wizard
نفّذ طريقة Wizard.DamagePoints() لتُرجع نقاط الضرر التي يلحقها: 12 نقطة ضرر عند تجهيز تعويذة، و3 نقاط ضرر عند عدم تجهيزها.
var wizard = new Wizard();
var warrior = new Warrior();
wizard.PrepareSpell();
wizard.DamagePoints(warrior);
// => 12
Warrior
نفّذ طريقة Warrior.DamagePoints() لتُرجع نقاط الضرر التي يلحقها: 10 نقاط ضرر عندما يكون الهدف عرضة للضرر، و6 نقاط ضرر عندما لا يكون.
var warrior = new Warrior();
var wizard = new Wizard();
warrior.DamagePoints(wizard);
// => 10
سجّل في Exercism لتتعلّم وتتقن C# عبر 62 مفهومًا178 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.