الفئات ومقدمة إلى البرمجة كائنية التوجه
#1
ألسلام عليكم و رحمة الله تعالى و براكته

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

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

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

دلفي هي توسيع غرضي_التوجة للغة باسكال التقليدية .وما **** التنوية إلية هنا أن الصياغة النحوية للغة الباسكال مشهورة بإنها صياغة أكثر وضوحا وقابلية للقراءة من معظم اللغات الأخرى (ولنقل مثلا لغة C ) , وبالتالي كمية أكبر من الحشو من أجل الحصول على شفرة مقروءة تشبة الكلام العادي بحيث يمكن فهمها وتذكرها بشكل سريع ومنتظم وهذا مما يقل من الوقوع بالأخطاء .
كما أن التوسع الغرضي_التوحه لهذة الغة بإعتراف الجميع لا يقل أهمية عن الموجود في النسل الحالي للغات البرمجة الغرضية من Java حتى C#
الرد
#2
وعليكم السلام ورحمة الله وبركاته
يعتبر البعض أن مجرد إمكانية التوليف باستخدام مناهج متسلسلة (البرمجة الإجرائية Procedural)
خطر على الشركة والمبرمج، وهو مما يعاب على [مستخدمي] دلفي!
ما رأيك؟
الرد
#3
شكرا اخي الكريم
شكرا على نقل المشارك الى موضوع جديد بقية مشارك اخرى ****ان تقوم بنقلها فصلحباتي محدودة جدا
موافق 100"
إقتباس :وهو مما يعاب على [مستخدمي] دلفي!
لا فهناك الكثير يعتمدون على OOP و من بينهم انا ودعت البرمجة باستخدام المناهج منذوا فترة طويلة الا للبرامجة القديمة التي لم نغيرها و الان الحمد لله مع الدوت نت انا مجبر على هذا النوع من البرمجة لان اغلب المشاريع اما تعتمد على ORM في التعامل مع قواعد البيان او انه اختارفية جدا وهو المشروع الذي اعمل عليه حاليا في WPF لكني مبتدا .
ومكونات الدلفي VCL ايضا لم تعطي امكانيت التعامل مع الاشياء عن طريق خاصية مثل ماهو في البريسم datasours
سنحاول قدر المستطاع شرح هذا لكي يستطيع الجميع التنقل بين اللعات دون مشكل c# prism java
الرد
#4
يمكن ان يحتوي البرنامج على عدة فئات ، ويمكن ان تحتوي الفئة ايضاً على عدة فئات بداخله ، في
.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 ونتبعه مباشرة بتعريف الحقول الخاصة به , ثم رؤوس المناهج التي يعرفها , وبالتأكيد ننهي ذلك بـ
الرد
#5
تعريف حقل صنف
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 وخاص بالصنف .
الرد
#6
كما تلاحضون اننا انشانا حقل من نوع 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) , حيث لا تضطر أن تعرف كيف تتم الأمور بالداخل وما هي المحتويات الداخلية , وكل ما يهمك هو كيف تتعامل مع واجهة الصندوق الأسود وتعطية معطياتك وتأخذ النتائج بغض النظر عن ما يتم في الداخل . إن ما يهمك فعليا من الصندوق هو آلية التعامل معة (مع واجهتة) ولا تعطي إهتماما كبيرا عن تفاصيل داخل الصندوق , مثلا يهمك أن تتفرج على البرامج المفضله على التلفزيون وأن تعرف تغيير المحطات وإطفاءة وتشغيلة , بغض النظر عن فهم الدارات الداخلية المكونة للتلفزيون ..
الرد
#7
ملاحضة
هناك ثلاث اشكال للتعريف بالحقول
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;
الرد
#8
يمكن ايضاً ان يستقبل الباني بارميترس، فمثلاً نريد تغيير القيمة الافتراضية بقيمة نحددها في كل مرة ننشا الغرض .

[COLOR="DarkOrange"]ملاحضة هامة سنرجع اليها بعد قليل
يكن للصنف ان يحتوي على عدة مشيدلت او بواني
[/COLOR]
كود :
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;
الرد
#9
المهدمات 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;
الرد
#10
الكلمة المحجوزة 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(MyStaticClass.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(MyStaticClass.MyVariable));
end;
الرد


التنقل السريع :


مستخدمين يتصفحوا هذا الموضوع: 1 ضيف