المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : الفئات ومقدمة إلى البرمجة كائنية التوجه


زكيري عبدالعالي
25-06-2011, 04:51 PM
ألسلام عليكم و رحمة الله تعالى و براكته

ساعتمد في شرحي و تعاريفي على كتابين الولل للاستاذ علي عروة و الثاني للاستاذ احمد جمال خليفة
سنقوم بشرح مفصل للبرمجة الشيئية للدلفي و البريسم
غرضية التوجة في دلفي object-oriented in Delphi :

إن معظم اللغات الحديثة تدعم البرمجة غرضية التوجة (OOP) أو object-oriented programming , حتى أن مقدار دعم اللغة للـ OOP أصبح ينظر إلية في كثير من الأحيان كمقياس يعبر عن أهمية اللغة .
تعتمد البرمجة غرضية التوجة على ثلاث مفاهيم أساسية سنعالجها في هذا الفصل :

- التغليف encapsulation .
- الوراثة inheritance .
- تعددية الأشكال polymorphism .

دلفي هي توسيع غرضي_التوجة للغة باسكال التقليدية .وما **** التنوية إلية هنا أن الصياغة النحوية للغة الباسكال مشهورة بإنها صياغة أكثر وضوحا وقابلية للقراءة من معظم اللغات الأخرى (ولنقل مثلا لغة C ) , وبالتالي كمية أكبر من الحشو من أجل الحصول على شفرة مقروءة تشبة الكلام العادي بحيث يمكن فهمها وتذكرها بشكل سريع ومنتظم وهذا مما يقل من الوقوع بالأخطاء .
كما أن التوسع الغرضي_التوحه لهذة الغة بإعتراف الجميع لا يقل أهمية عن الموجود في النسل الحالي للغات البرمجة الغرضية من Java حتى C#

kachwahed
25-06-2011, 05:59 PM
وعليكم السلام ورحمة الله وبركاته
يعتبر البعض أن مجرد إمكانية التوليف باستخدام مناهج متسلسلة (البرمجة الإجرائية Procedural)
خطر على الشركة والمبرمج، وهو مما يعاب على [مستخدمي] دلفي!
ما رأيك؟

زكيري عبدالعالي
25-06-2011, 06:29 PM
شكرا اخي الكريم
شكرا على نقل المشارك الى موضوع جديد بقية مشارك اخرى ****ان تقوم بنقلها فصلحباتي محدودة جدا
موافق 100"
وهو مما يعاب على [مستخدمي] دلفي!
لا فهناك الكثير يعتمدون على OOP و من بينهم انا ودعت البرمجة باستخدام المناهج منذوا فترة طويلة الا للبرامجة القديمة التي لم نغيرها و الان الحمد لله مع الدوت نت انا مجبر على هذا النوع من البرمجة لان اغلب المشاريع اما تعتمد على ORM في التعامل مع قواعد البيان او انه اختارفية جدا وهو المشروع الذي اعمل عليه حاليا في WPF لكني مبتدا .
ومكونات الدلفي VCL ايضا لم تعطي امكانيت التعامل مع الاشياء عن طريق خاصية مثل ماهو في البريسم datasours
سنحاول قدر المستطاع شرح هذا لكي يستطيع الجميع التنقل بين اللعات دون مشكل c# prism java

زكيري عبدالعالي
25-06-2011, 09:34 PM
يمكن ان يحتوي البرنامج على عدة فئات ، ويمكن ان تحتوي الفئة ايضاً على عدة فئات بداخله ، في
.Project من New Class منفصل يمكنك اضافة Class حالة رغبتك في عمل
يتم تعريف الفئة باستخدام الكلمة المحجوزة class
سنقوم بادراج فئة جديدة ،ونسميها باسم MyClass سنجد الكود التالي موجوداً بصورة افتراضية:

خاص بالبريسم
الجزء الأول الذي يحدد ال namespace ضروري ، حيث يعني هذا ان جميع الفئات الموجودة تحت نفس
namespace يمكنها رؤية بعضها الآخر ، لذا سنتمكن من التعامل مع الفئة الجديدة من خلال main الخاصة بنا في الفئة الاساسية المسماه Program
عريف الأصناف في دلفي :
لتعريف صنف جديد في دلفي , دعنا نتذكر أن الصنف يحوي شيئين مهمين هما الحقول (بيانات الصنف) والمناهج (عمليات الصنف) .
بناء صنف جديد موضوع سهل في دلفي .

DELPHI
unit MyClassFile;
interface
type
Mycalss = class end;
implementation
end.

PRISM
namespace MyProject;
interface
type
MyClass = class end;
implementation
end.

إذا فكرنا بناءً على ما سبق ماذا نحتاج لنعرف صنف جديد , لوجدنا أننا نريد تعريف الحقول التي يحويها هذا الصنف والعمليات التي يستطيع إنجازها , وبالتأكيد نعرف له إسما فريدا خاص به .
الحقول هي عبارة عن متحولات عادية , والعمليات هي عبارة عن مناهج (أي توابع أو إجراءات) . تنسيق هذا التعريف يتم بصورة بسيطة – بإن نذكر في قسم Type إسم الصنف محدداً بالكلمة المفتاحية Class ونتبعه مباشرة بتعريف الحقول الخاصة به , ثم رؤوس المناهج التي يعرفها , وبالتأكيد ننهي ذلك بـ

زكيري عبدالعالي
25-06-2011, 10:03 PM
تعريف حقل صنف
DELPHI
MyClass = class
private _myField: string;
published property MyField : string read _myField write _myField;
end;
PRISM
MyClass = class
private _mMyField: string;
public property MyField : string read _mMyField write _mMyField;
end;

إذا ضغطت Ctrl+Shift+C عندما يكون المؤشر ضمن تعريف الصنف , فإن ميزة تكميل التعريف في دلفي سوف تقوم تلقائيا بمساعدتك وتوليد هيكل التعريف الخاص بالمناهج التي قمت بتعريفها في الصنف .
كما تلاحضون اننا انشانا حقل من نوع string وخاص بالصنف .

زكيري عبدالعالي
25-06-2011, 10:41 PM
كما تلاحضون اننا انشانا حقل من نوع string وخاص بالصنف و نستطيع الوصول اليه عن طريق خاصية (يمكن ان يكون تابع) سواء للقراء او الكتابة في هذا الحفل .
*- تغيير قيمة الحقل
DELPHI
var MyObeject : MyClassFile.Mycalss;
begin
MyObeject := MyClassFile.Mycalss.Create();
MyObeject.MyField:='FieldValue';
end;

PRISM
var MyObject := new MyProject.MyClass();
MyObject.MyField := 'FieldValue';
ومن هنا ستعرف كيف تقرا قيمة الحقل وحدك .

التغليف Encapsulation :
تعتمد فكرة غرضية التوجة على إخفاء البيانات . وتستخدم الأصناف لتحقيق ذلك .
يتم إخفاء البيانات داخل الأصناف الخاصة بها , أو نقول يتم تغليف البيانات داخل الأصناف .
عادة يتم توضيح هذة الفكرة بإستخدام ما يسمى الصناديق السوداء (black boxes) , حيث لا تضطر أن تعرف كيف تتم الأمور بالداخل وما هي المحتويات الداخلية , وكل ما يهمك هو كيف تتعامل مع واجهة الصندوق الأسود وتعطية معطياتك وتأخذ النتائج بغض النظر عن ما يتم في الداخل . إن ما يهمك فعليا من الصندوق هو آلية التعامل معة (مع واجهتة) ولا تعطي إهتماما كبيرا عن تفاصيل داخل الصندوق , مثلا يهمك أن تتفرج على البرامج المفضله على التلفزيون وأن تعرف تغيير المحطات وإطفاءة وتشغيلة , بغض النظر عن فهم الدارات الداخلية المكونة للتلفزيون ..

زكيري عبدالعالي
26-06-2011, 08:34 AM
ملاحضة
هناك ثلاث اشكال للتعريف بالحقول
1- published property MyField : string read _myField write _myField;
2- published property MyField : string read _myField write SetMyField;
3- published property MyField : string read GetMyField write SetMyField;
لحالة الأولى : وهي أبسط الحالات , أن نقوم بتعريف متحول ما _myField مثلا من أجل القراءة والكتابة , بدون إستخدام أي منهج , القراءة تتم منه والكتابة إلية , وطبعا لا يمكن هنا التأكد من صحة الإدخال , أو إرفاق إدخال أو إخراج القيمة بحدث ما .
الحالة الثانية :قمنا بالقراءة من متحول (_myField ) بشكل طبيعي مثل الحالة الأولى , حيث أنة في كثير من الأحيان لا نحتاج التأكد من صحة الإخراج طالما كنا قد تأكدنا من صحة الإدخال منذ البداية .
أما الكتابة فتتم بإستخدام الإجرائية SetMyField, وهنا نستطيع التأكد من صلاحية الأدخال أو إرفاق الإدخال بأحداث ما (إلغاء تعطيل خواص معينة بعد الإدخال مثلا) , وبالطبع هذة الحالة مستخدمة كثيرا على عكس الحالة الأولى .
الحالة الثالثة : إستخدمنا التابع GetMyField للإدخال والإجرائية SetMyFieldللإخراج , وهي الحالة العامة .

الباني Constructor :
الباني هو منهج خاص يستخدم لحجز الذاكرة لمنتسخ من صنف ليصبح جاهزاً للإستخدام , وكنا قد سميناه المنهج Create في مامضى , الحقيقة التي ****ك أن تعرفها عن الباني أنة يعيد الغرض كقيمة جاهزة للإستخدام حيث نستطيع نسية إلى متحول موجود لكي نستخدمة لاحقا . أي كأنة تابع قيمتة المعادة هي الغرض نفسة

DELPHI
في الدلفي كلمة constructor هي التي تستعمل لتعريف باني او مشيد
unit MyClassFile;
interface
type
Mycalss = class
private _mMyField: string;
public property MyField : string read _mMyField write _mMyField;
public constructor Create();
end;
implementation

constructor Mycalss.Create();
begin
Self._mMyField := 'قيمة افتراضية للحقل ';
end;

end.
كما تلاحضون اننا قمنا بانشاء مشيد يقوم بتغير قيمة الحقل الى قيمة افترضية .
لو قمنا بانشاء شئ جديد او غرض جديد و عرضنا حقله بالطريقة التالية
procedure TForm1.Button1Click(Sender: TObject);
var MyObeject : MyClassFile.Mycalss;
begin
MyObeject := MyClassFile.Mycalss.Create();
showmessage(MyObeject.MyField);
end;

النتيجة
قيمة افتراضية للحقل

PRISM
namespace MyProject;
interface
type

MyClass = class
private _mMyField: string;
public property MyField : string read _mMyField write _mMyField;
constructor();
end;

implementation
constructor MyClass();
begin
self._mMyField := 'قيمة افتراضية للحقل ';
end;

end.
انشاء شئ جديد او غرض جديد و عرضنا حقله بالطريقة التالية
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
var MyObject := new MyProject.MyClass();
MessageBox.Show(MyObject.MyField);
end;

زكيري عبدالعالي
26-06-2011, 08:50 AM
يمكن ايضاً ان يستقبل الباني بارميترس، فمثلاً نريد تغيير القيمة الافتراضية بقيمة نحددها في كل مرة ننشا الغرض .

ملاحضة هامة سنرجع اليها بعد قليل
يكن للصنف ان يحتوي على عدة مشيدلت او بواني


unit MyClassFile;
interface
type
Mycalss = class
private _mMyField: string;
public property MyField : string read _mMyField write _mMyField;
public constructor Create(); overload ;
public constructor Create( mYFieldVariable : string ) ; overload ;
end;
implementation

constructor Mycalss.Create();
begin
Self._mMyField := 'قيمة افتراضية للحقل ';
end;

constructor Mycalss.Create(mYFieldVariable : string);
begin
Self._mMyField := mYFieldVariable;
end;
end.


procedure TForm1.Button1Click(Sender: TObject);
var MyObeject : MyClassFile.Mycalss;
begin
MyObeject := MyClassFile.Mycalss.Create('تمرير فيمة افتراضية جديدة');
showmessage(MyObeject.MyField);
end;

PRISM
namespace MyProject;
interface
type

MyClass = class
private _mMyField: string;
public property MyField : string read _mMyField write _mMyField;
constructor();
constructor ( mYFieldVariable : string ) ;
end;

implementation
constructor MyClass();
begin
self._mMyField := 'قيمة افتراضية للحقل ';
end;

constructor MyClass( mYFieldVariable : string ) ;
begin
Self._mMyField := mYFieldVariable;
end;

end.


method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
var MyObject := new MyProject.MyClass('تمرير فيمة افتراضية جديدة');
MessageBox.Show(MyObject.MyField);
end;

زكيري عبدالعالي
29-06-2011, 11:05 PM
المهدمات Destructor
عكس ال ،Constructor يتم اطلاق هذا الحدث مع انهاء استخدام الObject
يمكن كتابة هادم خاص لة . ويقوم بالعمل المعاكس حيث يحرر أي ذاكرة قام الباني بحجزها ولم تحرر فيما بعد . ويبدأ بالكلمة المفتاحية destructor و يكون إسمة Destroy .
سترى لاحقا إمكانية إستخدام الهادم القديم ضمن الجديد من أجل أن يقوم الصنف ببعض عمليات التنظيف دون أن نشغل بالنا فيها من جديد .
لا تستخدم أبدا إسم للهادم غير الإسم Destroy , لإن الأغراض يتم تحريرها عادة بالمنهج الشهير Free ومبدأ هذا المنهج(Free): هو إختبار إذا كانت قيمة الغرض Nil قبل أن يستدعي المنهج الهادم Destroy , وبالتالي فإن Free لن يتعرف على الهادم الجديد الذي قمنا ببناءة إذا لم يكن إسمة Destroy وستنتج أخطاء .
إن Free هي منهج للصنف الأب Tobject والذي ترثة كل الأغراض الأخرى .
والجدير بالذكر هنا أن Free لن تقوم بضبط قيمة الغرض إلى Nil بعد تحرير الذاكرة الخاصة به .لذلك عليك أن تقوم بذلك بنفسك والسبب بسيط أن الغرض لن يعرف ما هي المتحولات التي نسبت إلية , ولن يستطيع التأكد من أنه ضبط قيمة جميع هذة المتحولات إلى Nil , لذلك تركت العملية إلى المستخدم , ولكن دلفي تملك بعض الدوال ال****** هنا مثل الدالة FreeAndNil التي قد تساعد أحيانا . حيث أنها تحرر الغرض وتلغي المرجع الذي يشير إلية (يصبح المؤشر معرفا مثل أي متحول ولكنة لايشير إلى أي قيمة بالذاكرة ) .

DELPHI

published Destructor Destroy;
destructor Mycalss.Destroy;
begin
Self._mMyField := '';
ShowMessage('هدم الكائن');
end;

procedure TForm1.Button1Click(Sender: TObject);
var MyObeject : MyClassFile.Mycalss;
begin
MyObeject := MyClassFile.Mycalss.Create('تمرير فيمة افتراضية جديدة');
showmessage(MyObeject.MyField);
FreeAndNil(MyObeject);
end;

PRISM
public finalizer Finalize;

finalizer MyClass.Finalize;
begin
Self._mMyField := nil;
MessageBox.Show('هدم الكائن');
end;

method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
var MyObject := new MyProject.MyClass('تمرير فيمة افتراضية جديدة');
MessageBox.Show(MyObject.MyField);
end;

زكيري عبدالعالي
30-06-2011, 11:32 PM
الكلمة المحجوزة self
هي تمثل اسم اختصار للصنف المحدد و استخدامها سيكون مناسب دائماً ،
ابسط اسباب ذلك هو اظهار قائمة بالعناصر الموجودة في الاوبجكت وقت البرمجة منذ للحظة التي تكتب فيها self.

Static Class

لا بد ان تكون جميع المتغيرات والدوال فيه من نوع static اضف إلى ذلك فإنه ليس من المنطقي تعريف object من هذا الفئة Class باستخدامNEW او CREATE

DELPHI
MyStaticClass = class(TObject)
private {$HINTS OFF} constructor Create; {$HINTS ON}
public class var MyVariable: string;
public class function MyStaticMethod(MyParametre : string):string;
end;

constructor MyStaticClass.Create;
begin

end;

class function MyStaticClass.MyStaticMethod(MyParametre: string): string;
begin
Result := Copy(MyParametre,0,7);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
MyStaticClass.MyVariable:='zekiri abdelali';
showmessage(MyStaticClass.MyStaticMethod(MyStaticC lass.MyVariable));
end;

PRISM
MyStaticClass = static class
public constructor ();
public class var MyVariable: string;
public class method MyStaticMethod(MyParametre : string):string;
end;


constructor MyStaticClass() ;begin end;

class method MyStaticClass.MyStaticMethod(MyParametre : string): string;
begin
result := MyParametre.Split(' ')[0];
end;

method MainForm.button2_Click(sender: System.Object; e: System.EventArgs);
begin
MyStaticClass.MyVariable:='zekiri abdelali';
MessageBox.Show(MyStaticClass.MyStaticMethod(MySta ticClass.MyVariable));
end;