تاريخ التحديث: رقم 1
وقت التحديث: 2001-11-01 20:09
تم التحديث بواسطة: Musicwind®
ملاحظة التحديث: تم الانتهاء من المسودة الأولى.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~
ملخص:
تتناول هذه المقالة كيفية تصدير الفئات في ملف Dll - العديد من الفئات الفرعية بناءً على فئة مجردة محددة. تستخدم هذه التقنية فكرة تعدد الأشكال، مما يتيح لنا الحصول على تأثيرات مشابهة للمكونات الإضافية.
القراء المستهدفون:
فهم مفهوم تعدد الأشكال. فهم مفهوم metaclass.
الصعوبة الفنية:
6/10 .
لتصدير فئة من Dll، أول شيء يجب أن تفكر فيه هو استخدام حزمة bpl. أحد عيوب هذه الطريقة هو أن المستخدم يجب أن يعرف الفئات الموجودة في الحزمة، مما يعني أن اسم الفئة يجب أن يكون معروفًا - وهذا قيد بمعنى ما. تخيل موقفًا يحدد فيه المستخدم الطبقة السفلية فئة مجردة، ثم العديد من فئات التطبيق (خرسانة class)، فبالنسبة للمستخدم، يأمل أن يكون قادرًا على استخدام هذه الفئات دون معرفة الفئات المحددة - يبدو قول هذا غامضًا بعض الشيء، لكن الوضع الفعلي صحيح، لأنه لا يمكن التنبؤ به عند تعريف الفئات المجردة كيف سيكون هناك العديد من الفئات المحددة في المستقبل، فما هو نوع التكنولوجيا اللازمة لتحقيق مثل هذا الطلب؟
وفي الواقع فإن صعوبة تنفيذها من الناحية الفنية ليست صعبة للغاية - فالمؤلف هنا يهدي خبرته العملية للجميع، كوسيلة لجذب أفكار جديدة، ويأمل أن يرى أساليب أخرى أفضل!
يقدم ما يلي أولاً بعض المعرفة الأساسية المتعلقة بهذه الطريقة، ثم يستخدم مثالاً لتوضيح التنفيذ المحدد.
1. المفاهيم الأساسية
يمكن اعتبار فئة التعريف (فئة التعريف)، والتي تسمى أيضًا النوع المرجعي للفئة (نوع مرجع الفئة)، نوعًا من الفئة، وتمثل قيمة المتغير المُعلن بهذا النوع فئة. على سبيل المثال:
يكتب
TClass = فئة TObject؛
هذا يعلن عن نوع metaclass. ثم يمكنك الحصول على إعلانات متغيرة مثل هذا:
فار
الفئة: TClass؛
وبعد ذلك، يمكنك استخدامه على النحو التالي:
AClass := TObject;
أو:
AClass := TButton;
أو:
AClass := TForm;
إلخ.
نظرًا لأن TClass عبارة عن فئة تعريفية من النوع TObject، وTButton و TForm وما إلى ذلك كلها مشتقة من TObject، فإن القيم مثل TButton و TForm تكون مقبولة لدى AClass.
بعد ذلك، يمكننا استخدام فكرة تعدد الأشكال واستخدام متغير الفئة AClass بمرونة. هذه أيضًا المعرفة الأساسية للتنفيذ المحدد أدناه.
2. التنفيذ المحدد
الخطوة الأولى هي إنشاء فئة مجردة:
نحن نستخدم مثل هذا الإعلان البسيط، حيث توفر الفئة المجردة طريقة مجردة فقط، ولكنها لا تؤثر على وصفنا للمشكلة:
TMyBaseForm = الفئة(TForm)
محمي
وظيفة GetTitle: pchar الظاهري؛
نهاية؛
MyBaseFormClass = فئة TMyBaseForm؛
دعونا لا نناقش عدد الأساليب والواجهات العملية التي توفرها هذه الفئة المجردة، لأن ما نريد مناقشته هو الجدوى الفنية. افترض أن الهدف الأصلي للمؤلف من تعريف هذه الواجهة هو الحصول على أي عدد من العناوين المتغيرة، ويجب تنفيذ قيمة الإرجاع المحددة لـ GetTitle بواسطة الفئات الفرعية. علاوة على ذلك، يأمل المؤلف أيضًا أن يتم تنفيذ كود الفئة الفرعية في ملف Dll وفصله عن البرنامج الرئيسي - هذه الطريقة لها نكهة البرنامج الإضافي، وقد تكون أيضًا قادرة على تحقيق بعض ميزات التوصيل والتشغيل - ليست كذلك. هل هي جذابة للغاية؟ إذن، ماذا يجب أن تفعل بعد ذلك؟
أولاً، يجب أن يتضمن البرنامج الرئيسي وبرنامج Dll الوحدات المذكورة أعلاه، ثم يكون البرنامج الرئيسي مسؤولاً عن تنفيذ برنامج التشغيل - تحميل Dll ديناميكيًا وتحميل الفئات ديناميكيًا، ويكون Dll مسؤولاً عن تنفيذ الفئات الفرعية.
لنتحدث عن Dll أولاً، ما الذي يجب أن يفعله Dll؟
الخطوة الثانية هي تصدير الفئة الفرعية في Dll :
قمنا بتصميم الوظيفتين المصدرتين التاليتين:
1. وظيفة GetClassCount: عدد صحيح؛
أخبر المتصل بوجود عدة فئات فرعية في ملف Dll هذا؛
2. الدالة GetClassTypeByIndex(const iIndex: integer;
فار ClassType: MyBaseFormClass): WordBool؛
احصل على فئة فرعية محددة حسب الفهرس. لاحظ أن نوع ClassType هنا هو MyBaseFormClass، مما يشير إلى أن قيمته ستكون فئة محددة موروثة من TMyBaseForm.
فيما يلي أحد التطبيقات الممكنة لها:
وظيفة GetClassCount: عدد صحيح؛
يبدأ
النتيجة := 3; // يشير إلى أنه تم تصدير 3 فئات في ملف Dll هذا
نهاية؛
الدالة GetClassTypeByIndex(const iIndex: integer;
فار ClassType: MyBaseFormClass): WordBool؛
يبدأ
النتيجة := صحيح؛
حالة iIndex
0: ClassType := TFrmTest1;
1: ClassType := TFrmTest2;
2: ClassType := TFrmTest3;
آخر
النتيجة:= خطأ؛
نهاية؛
نهاية؛
وبطبيعة الحال، يجب تضمين الوحدات التي توجد بها TFrmTest1 وTFrmTest2 وTFrmTest3 في قائمة الاستخدام الخاصة بالوحدة. يمكن أن يكون تنفيذ TFrmTest1 كما يلي:
TFrmTest1 = فئة (TMyBaseForm)
محمي
وظيفة GetTitle: تجاوز PChar؛
نهاية؛
الدالة TFrmTest1.GetTitle: Pchar;
يبدأ
النتيجة := 'مرحبا من TFrmTest1'؛
نهاية؛
وأخيرًا، لا تنس إضافة GetClassCount وGetClassByIndex إلى قائمة الصادرات. بعد ذلك، عند إنشاء مشروع Dll، يرجى تحديد "استخدام حزمة وقت التشغيل" في حزمة خيارات المشروع. سيتم مناقشة الأسباب المحددة لاحقًا.
عند هذه النقطة، وصل العمل على Dll إلى نهايته.
الخطوة الثالثة هي تنفيذ محرك تشغيل البرنامج الرئيسي:
هذه الخطوة سهلة نسبيًا - فهي ليست أكثر من تحميل ملف Dll ديناميكيًا، ثم استدعاء الدالة GetClassCount، ثم استدعاء GetClassByIndex. رمز المفتاح:
فار AClass: TMyBaseClass؛
أفورم: تميباسفورم؛
أنا، iCount: عدد صحيح؛
نتيجة bl: منطقية؛
يبدأ
// احذف الجزء المتعلق بتحميل المكتبة الديناميكية، بافتراض أن FPGetClassProc يشير إلى وظيفة GetClassCount ويشير FPGetClassByIndexProc إلى GetClassByIndex، ثم:
iCount := FPGetClassProc;
لأني := 0 إلى iCount ؟C 1 افعل
يبدأ
AClass := FPGetClassByIndex(I, blResult);
إذا bl النتيجة بعد ذلك
يبدأ
AForm := AClass.Create(application);
AForm.Caption := AForm.GetTitle;
AForm.Show;
نهاية؛
نهاية؛
//...
نهاية؛
لاحظ أنه، كما هو الحال مع Dll، تحتاج أيضًا إلى اختيار استخدام حزمة وقت التشغيل عند إنشاء ملف الإخراج. وذلك لأن عدم استخدام حزمة وقت التشغيل سيؤدي إلى وجود نسخ متعددة من نفس الفئة في الذاكرة، لذا فإن استخدام عامل التشغيل Is عليها سيؤدي إلى إرجاع خطأ.
Musicwind®@HangZhou.Zhejiang.China
01/11/2001
المزيد من المقالات
[ نهاية المقال ]