الخميس، 30 ديسمبر 2010

المتباينات

لتوفير دعما كاملا لOLE، تضمنت نسخة 32-بت من دلفي نوع بيانات متباين Variany.هنا أريد أن أناقش نوع البيانات هذا من زاوية عامة. نوع متباين، في الواقع، أصبح له تأثير متزايد على كامل اللغة، لدرجة أن مكتبة مكوّنات دلفي تستخدم هذا النوع بطرق ليس لها علاقة ببرمجة OLE.

المتباينات ليس لها نوع
بصفة عامة، يمكنك استعمال المتباينات لتخزين أي نوع بيانات و لانجاز مختلف العمليات و تحويلات النوع. لاحظ أن هذا ضد التوجّه العام للغة باسكال و ضدّ أعراف البرمجة الجيدة. المتباين يتم فحص نوعه و يتم حسابه في وقت التشغيل. المجمّع compiler لن يحذرك من احتمالات الأخطاء في التوليف، و التي لن يستدلّ عليها إلا بعد اجراء اختبارات مكثفة. بصورة عامة، يمكنك اعتبار أجزاء التوليف التي تستخدم المتباينات هي لتوليف ترجمة فورية interpreted، لأنه، مثل أي توليف لترجمة فورية، العديد من العمليات لا يمكن التقرير بشأنها وحلّها إلى في وقت التشغيل. هذا يوثر بصفة خاصة في سرعة التوليف.

الآن و قد حذرتك من استخدام نوع المتباين، حان الوقت لرؤية ماذا يمكنه أن يفعل. أساسا حالما تقوم بتعريف متغير متباين مثل التالي:

var
V: Variant;يمكنك أن تخصّص له عدة أنواع مختلفة:

V := 10;
V := 'Hello, World';
V := 45.55;حالما تتحصل على قيمة متباين، يمكنك نسخه إلى أي نوع بيانات آخر متوافق أو غير متوافق. إذا خصصت قيمة لنوع بيانات غير متوافق، تقوم دلفي بإجراء التحويل، إذا استطاعت ذلك. و إلا فإنها ستصدر خطأ وقت التشغيل. في الواقع المتباين يخزن معلومات النوع رفق البيانات، لتسمح بعدد من العمليات في وقت التشغيل؛ هذه العمليات قد تكون مفيدة لكنها بطيئة و غير مأمونة.

أنظر إلى المثال التالي (اسمه VariTest)، و الذى هو توسيع للتوليف أعلاه. قمت بوضع ثلاث خانات كتابة على نموذج form جديد، و اضفت بعض الأزرار، ثم كتبت التوليف التالي لحدث OnClick للزرّ الأول:

procedure TForm1.Button1Click(Sender: TObject);
var
V: Variant;
begin
V := 10;
Edit1.Text := V;
V := 'Hello, World';
Edit2.Text := V;
V := 45.55;
Edit3.Text := V;
end;أمر مضحك، أليس كذلك؟ فبجانب تخصيص متباين يحوي جملة إلى سمة Text في مكون خانة الكتابة، يمكنك تخصيص متباين يحوي رقما صحيحا أو رقم نقطة عائمة إلى نفس سمة Text.

الشكل 10.1: ناتج مثال VariTest بعد الضغط على زرّ Assign



أسوأ من هذا، يمكنك استخدام المتباينات لحساب القيم، كما تري في التوليف المتصل بالزرّ الثاني:

procedure TForm1.Button2Click(Sender: TObject);
var
V: Variant;
N: Integer;
begin
V := Edit1.Text;
N := Integer(V) * 2;
V := N;
Edit1.Text := V;
end;كتابة مثل هذا التوليف فيه مخاطرة، أقلّها، إذا احتوت خانة الكتابة الأولى على رقم، فكل شيء سيعمل، غير ذلك، سيبرز اعتراض exception. مرّة أخرى يمكنك كتابة توليف مشابه، لكن في حالة عدم وجود سبب ضاغط، يجب أن تتجنب نوع المتباين؛ تشبت بأنواع بيانات باسكال التقليدية و بأسلوب تفحّص النوع. في دلفي و في مكتبة المكونات المرئية VCL، تستخدم المتباينات أساسا لدعم تقنية OLE و لمناولة حقول قواعد البيانات.

المتباينات، نظرة أعمق
تتضمّن دلفي نوع تسجيلة متباينة variant record type و هي، TVarData، والذي له نفس توزيع الذاكرة الذي لنوع متباين Variant. يمكنك استعماله للوصول إلى النوع الفعلي للمتباين. بنية TVarData تتضمن نوع المتباين هذا، مشار إليه بحقل VType، و بعض الحقول المحجوزة، و القيمة الفعلية.

القيم المحتملة لحقل VType تتطابق مع أنواع البيانات التي يمكنك استعمالها في آلية OLE، و التي غالبا ما تسمّى بأنواع OLE أو أنواع متباينة. فيمل يلي سرد أبجدي كامل لأنواع المتباين المتوفرة:

varArray
varBoolean
varByRef
varCurrency
varDate
varDispatch
varDouble
varEmpty
varError
varInteger
varNull
varOleStr
varSingle
varSmallint
varString
varTypeMask
varUnknown
varVariant
يمكنك ايجاد أوصاف هذه الأنواع في موضوع VarType function في نظام مساعدة دلفي.

هناك أيضا العديد من الوظائف من أجل العمليات على المتباينات يمكنك استخدامها لصنع تحويلات معينة أو لطلب معلومات عن النوع الذي يحمله المتباين (انظر، مثلا، وظيفة VarType). معظم تحويلات النوع و وظائف التخصيص هذه فعليا يتم استدعاؤها بصورة آلية عندما تكتب تعبيرات تستخدم فيها المتباينات. إجرائيات أخرى تدعم نوع متباين (راجع موضوع Variant support routines في ملف المساعدة) تقوم أيضا بعمليات على المصفوفات المتباينة.

المتباينات نوع بطئ!
التوليف الذي يستخدم نوع متباين سيكون بطئ، ليس فقط عندما تقوم بتحويل أنواع البيانات، و لكن أيضا عندما تجمع قيم متباينين يحمل كلاهما عددا صحيحا. هي تقريبا بطيئة مثلها مثل التوليف المترجم لفيجوال بيسك! من أجل مقارنة سرعة خوارزمية مبنية على المتباينات مع أخرى بتوليف مشابه و معتمد على أعداد صحيحة، يمكنك النظر إلى مثال VSpeed:

هذا البرنامج ينفذ حلقة loop، مع قياس سرعتها، عارضا حالته في قضيب انجاز progress bar. فيما يلي أولى الحلقتين المتشابهتين، المبنيتين على الأعداد الصحيحة و المتباينات:

procedure TForm1.Button1Click(Sender: TObject);
var
time1, time2: TDateTime;
n1, n2: Variant;
begin
time1 := Now;
n1 := 0;
n2 := 0;
ProgressBar1.Position := 0;
while n1 < 5000000 do
begin
n2 := n2 + n1;
Inc (n1);
if (n1 mod 50000) = 0 then
begin
ProgressBar1.Position := n1 div 50000;
Application.ProcessMessages;
end;
end;
// we must use the result
Total := n2;
time2 := Now;
Label1.Caption := FormatDateTime (
'n:ss', Time2-Time1) + ' seconds';
end;توليف قياس الوقت يستحق النظر، لأنه شيئ يمكنك تطويعه بسهولة لأي نوع من اختبارات الأداء. كما ترى، يستخدم البرنامج وظيفة Now للحصول على قيمة الوقت الحالي و وظيفة FormatDateTime لعرض الفرق في الوقت، طالبين فقط الدقائق ("n") و الثواني ("ss") في الجملة المصاغة. كبديل، يمكنك استخدام وظيفة API ويندوز GetTickCount، و التي ترجع مؤشر دقيق جدا لمقدار جزء من ألف من الثانية قد مرّت منذ أن بدأ نظام التشغيل.

في هذا المثال فرق السرعة حقيقة كبير جدا لدرجة تلاحظها حتى بدون قياس دقيق للوقت. على كل حال، يمكن رؤية النتائج على حاسوبي الخاص في الشكل 10.2. القيم الفعلية تعتمد على الحاسوب الذي تستخدمه لتشغيل هذا البرنامج، لكن التناسب لن يتغير كثيرا.

الشكل 10.2: فرق السرعات لنفس الخوارزمية، مبنية على أعداد صحيحة و على المتباينات (الوقت الفعلي يتباين من حاسوب لآخر)، كما هو معروض من قبل مثال VSpeed



وجدان محمد الشبرين

ليست هناك تعليقات:

إرسال تعليق