تحميل العوامل (Operator Overloading)
جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 36 من 70.
يتيح لك تحميل المعاملات (Operator overloading) تحديد كيفية تصرف المعاملات مثل +، أو -، أو == مع فئاتك المخصصة. فبدلاً من استدعاء دوال مثل point1.Add(point2)، يمكنك كتابة التعبير الأكثر طبيعية point1 + point2.
لتحميل عامل تشغيل بشكل زائد (overload)، تقوم بإنشاء طريقة ثابتة (static method) خاصة باستخدام الكلمة المفتاحية operator:
public class Vector
{
public int X { get; }
public int Y { get; }
public Vector(int x, int y)
{
X = x;
Y = y;
}
public static Vector operator +(Vector a, Vector b)
{
return new Vector(a.X + b.X, a.Y + b.Y);
}
}الآن يمكنك إضافة المتجهات بشكل طبيعي:
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector v3 = v1 + v2; // X = 4, Y = 6يجب أن يكون التابع public static، ويجب أن يكون معامل واحد على الأقل من النوع المحتوي. يمكنك تحميل المعاملات الحسابية بشكل زائد (+، -، *، /)، ومعاملات المقارنة (==، !=، <، >)، والمعاملات الأحادية (-، !، ++).
لاحظ أن عوامل المقارنة يجب تحميلها بشكل زائد في أزواج - إذا قمت بتعريف ==، يجب عليك أيضاً تعريف !=.
استخدم تحميل المعاملات الزائد (operator overloading) عندما يجعل الكود الخاص بك أكثر بديهية، خاصة للأنواع الرياضية مثل المتجهات، الأعداد المركبة، أو العملات. وتجنب ذلك عندما لا يكون معنى العملية واضحاً على الفور.
التحدي
سهللنقم ببناء فئة Fraction تجعل العمل مع الكسور يبدو طبيعياً من خلال تحميل المعاملات بشكل زائد (operator overloading). بدلاً من استدعاء دوال مثل fraction1.Add(fraction2)، ستتمكن من كتابة fraction1 + fraction2 البديهية.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
Fraction.cs: أنشئ فئةFractionداخل مساحة الأسماءMathلتمثيل كسر يتكون من بسط ومقام. يجب أن يحتوي الكسر الخاص بك على:- خاصيتين للقراءة فقط من نوع 정수 (integer):
NumeratorوDenominator - مشد (constructor) يقبل البسط والمقام (بهذا الترتيب)
- تحميل زائد للمعامل
+يقوم بجمع كسرين باستخدام الصيغة:(a/b) + (c/d) = (a*d + c*b) / (b*d) - تحميل زائد للمعامل
*يقوم بضرب كسرين:(a/b) * (c/d) = (a*c) / (b*d) - تحميل زائد للمعامل
==يعيدtrueإذا كان الكسران متساويين (استخدم الضرب التبادلي للمقارنة:a*d == c*b) - تحميل زائد للمعامل
!=(مطلوب عند تحميل==بشكل زائد) يعيد عكس نتيجة== - دالة
GetDisplay()تعيد الكسر كسلسلة نصية بالتنسيق"{Numerator}/{Denominator}"
- خاصيتين للقراءة فقط من نوع 정수 (integer):
Program.cs: في ملفك الرئيسي، أنشئ كسرين باستخدام قيم المدخلات. استعرض المعاملات المحملة بشكل زائد عن طريق جمعها، وضربها، والتحقق مما إذا كانت متساوية. اطبع النتائج لإظهار عمل المعاملات بشكل طبيعي.
ستتلقى أربعة مدخلات:
- بسط الكسر الأول (عدد صحيح)
- مقام الكسر الأول (عدد صحيح)
- بسط الكسر الثاني (عدد صحيح)
- مقام الكسر الثاني (عدد صحيح)
اطبع المخرجات بهذا التنسيق:
Fraction 1: {GetDisplay()}
Fraction 2: {GetDisplay()}
Sum: {GetDisplay()}
Product: {GetDisplay()}
Are equal: {True/False}على سبيل المثال، إذا كانت المدخلات هي 1، 2، 2، و 4، يجب أن تكون المخرجات:
Fraction 1: 1/2
Fraction 2: 2/4
Sum: 8/8
Product: 2/8
Are equal: Trueلاحظ كيف تم التعرف على 1/2 و 2/4 على أنهما متساويان لأن 1*4 == 2*2. يتم حساب المجموع والناتج دون تبسيط - وهذا أمر جيد لهذا التحدي. الجمال يكمن في مدى الطبيعية التي يمكنك بها الآن التعامل مع الكسور باستخدام معاملات مألوفة!
ورقة مرجعية
يسمح لك تحميل المعاملات الزائد (Operator overloading) بتحديد سلوك مخصص للمعاملات مثل + و - و * و == مع الفئات (classes) الخاصة بك.
لتحميل معامل بشكل زائد، قم بإنشاء طريقة public static باستخدام الكلمة المفتاحية operator. يجب أن يكون أحد المعاملات على الأقل من النوع المحتوي:
public class Vector
{
public int X { get; }
public int Y { get; }
public Vector(int x, int y)
{
X = x;
Y = y;
}
public static Vector operator +(Vector a, Vector b)
{
return new Vector(a.X + b.X, a.Y + b.Y);
}
}الاستخدام:
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector v3 = v1 + v2; // X = 4, Y = 6يمكنك تحميل ما يلي بشكل زائد:
- المعاملات الحسابية:
+،-،*،/ - معاملات المقارنة:
==،!=،<،>(يجب تحميلها في أزواج) - المعاملات الأحادية:
-،!،++
عند تحميل == بشكل زائد، يجب عليك أيضاً تحميل !=:
public static bool operator ==(Vector a, Vector b)
{
return a.X == b.X && a.Y == b.Y;
}
public static bool operator !=(Vector a, Vector b)
{
return !(a == b);
}جرّب بنفسك
using System;
using Math;
class Program
{
public static void Main(string[] args)
{
// قراءة المدخلات للكسر الأول
int num1 = Convert.ToInt32(Console.ReadLine());
int den1 = Convert.ToInt32(Console.ReadLine());
// قراءة المدخلات للكسر الثاني
int num2 = Convert.ToInt32(Console.ReadLine());
int den2 = Convert.ToInt32(Console.ReadLine());
// TODO: إنشاء كائنين من نوع Fraction باستخدام قيم المدخلات
// TODO: استخدام معامل + الزائد (overloaded) لجمع الكسور
// TODO: استخدام معامل * الزائد (overloaded) لضرب الكسور
// TODO: استخدام معامل == الزائد (overloaded) للتحقق من التساوي
// TODO: طباعة المخرجات بالتنسيق المطلوب:
// Fraction 1: {GetDisplay()}
// Fraction 2: {GetDisplay()}
// Sum: {GetDisplay()}
// Product: {GetDisplay()}
// Are equal: {True/False}
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةNamespaces والتوجيهاتمقدمة في Classes و Objectsالكلمة المفتاحية 'this'Methods والمعاملاتFields مقابل PropertiesConstructorsObject Initializersمراجعة - آلة حاسبة بسيطة4الوراثة
صيغة الوراثة الأساسية (:)الكلمة المفتاحية 'base'الكلمات المفتاحية Virtual و Overrideالأصناف المختومة (Sealed Classes)الفئة الأساسية 'object'مراجعة - هيكلية الموظفين7ميزات متقدمة
تحميل العوامل (Operator Overloading)المفهرسات (Indexers (this[]))إعادة تعريف ()ToStringدوال التوسعة (Extension Methods)ملخص - Custom List2الخصائص والأعضاء الساكنة (Static Members)
الخصائص المطبقة تلقائيًا (Auto-Implemented Properties)خصائص القراءة فقط والكتابة فقطالحقول والدوال الساكنة (Static)الفئات الساكنة (Static Classes)الأعضاء ذات البنية التعبيرية (Expression-Bodied Members)5تعدد الأشكال والواجهات (Polymorphism & Interfaces)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالواجهة مقابل الفئة المجردة (Abstract Class)الواجهات المتعددةالواجهات الصريحةUpcasting و Downcastingملخص - حاسبة الأشكال8مفاهيم البرمجة كائنية التوجه (OOP) المتقدمة
التركيب بدلاً من الوراثةالـ Generics (الأصناف والدوال)الـ Delegates والأحداثالـ Attributes والـ Reflectionواجهة IDisposable وجملة usingأساسيات Dependency Injection