المشاركات : 306
المواضيع 45
:
: 0
الإنتساب : Jul 2012
السلام عليكم ورحمة الله وبركاتة
لتو بدأت مع الـ OOP بشكل جاد

, وها أنا في اول المطبات
سؤالي هو كتالي : كيف اقوم بنسخ محتويات كلاس إلى كلاس آخر ؟
لدي هذا الكود :
PHP كود :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyClass = class
private
FAge: Integer;
FName: string;
FPhoneNumbers: TStringList;
procedure setPhoneNumbers(const Value: TStringList);
public
property Name : string read FName write FName;
property Age : Integer read FAge write FAge;
property PhoneNumbers: TStringList read FPhoneNumbers
write setPhoneNumbers;
end;
var
Form1: TForm1;
Man1, Man2 : TMyClass;
implementation
{$R *.dfm}
{ TMyClass }
procedure TMyClass.setPhoneNumbers(const Value: TStringList);
var
i : Integer;
begin
for i := 0 to Value.count-1 do
begin
FPhoneNumbers.Add(Value.Strings[i]);
end;
end;
procedure TForm1.btn1Click(Sender: TObject);
begin
// create Man1 and fill its infos
Man1 := TMyClass.Create;
Man1.Name := 'Kahld';
Man1.Age := 15;
Man1.PhoneNumbers.Add('XXXXXXXXXXXX');
Man1.PhoneNumbers.Add('AAAAAAAAAAAA');
Man1.PhoneNumbers.Add('WWWWWWWWWWWW');
// Create Man2 and copy information form Man1
//to Man2 ; How Can I do that ?
Man2 := TMyClass.Create;
// if I use this code
Man2 := Man1; // I give Man2 a pointer for Man1
//so .. If i Free Man1.. Man2 will fo as well
end;
end.
كيف أقوم بنسخ محتويات Man1 إلى Man2 ؟
اريــ ـد نسخ المحتويات وليس إعطاء Man2 مؤشر إلى محتويات Man1
حيث لو قمت بإستدعاء الدالة Free لـ Man1 , ستذهب المعلومات من Man2 كذلك !
وكذلك نفطة آخرى .. عندما استعمل الأمر :
PHP كود :
Man1.PhoneNumbers.Add('XXXXXXXXXXXX');
يحصل خطا حيث اني لم أعمل Create للقائمة .. هل يجب ان اعدل الدالة Create الخاصة بالكلاس واضع فيها امر انشاء القائمة ؟
اتمنى اني وضحت المشكلة
وشكراً لحسن القارءة
المشاركات : 632
المواضيع 66
:
: 6
الإنتساب : Jul 2010
السلام عليكم ..
فكرة رائعة و صائبة أن تتعلم ال oop .. صدقني عندما تتقنها ستندم لأنك لم تتعلمها في وقت سابق :eek:
إقتباس :سؤالي هو كتالي : كيف اقوم بنسخ محتويات كلاس إلى كلاس آخر ؟
للأسف , دلفي لا تدعم بشكل مباشر نسخ كلاس الى كلاس آخر .
لكن يمكن تطبيقها بطريقتين :
- الطريقة الأولى استعمال ال RTTI :
تعتمد هذه الطريقة على enum لجميع ال properties ثم اسناد قيمها الى الكلاس .
أسلوب عملها مشابه تماما لل Object Inspector .
بما أنك تتعلم خطوة بخطوة .. فأنا لا أنصحك باستعمالها حتى تتقن ال OOP بشكل جيد .
-الطريقة الثانية توريث الكلاس من TPersistent :
الكلاس TPersistent يحتوي على اجراء assign لنسخ الكلاس ..
لعلك لاحظت أن أغلب الكلاسات مورثة منه : TCanvas,TFont,TButton,..
الفكرة تعتمد على عمل override للاجراء AssignTo ثم اسناد القيم الى الكلاس الجديد .
ملاحظة : الطريقة الثانية هي الطريقة الشائعة في نسخ الكلاسات 
-------------------------------------------------------------------
دائما اجعل أول حرف من الدالة uppercase ..
PHP كود :
setPhoneNumbers
=> SetPhoneNumbers
لمبرمجي دلفي فلسفة مع طريقة كتابة المتغيرات و الدوال في الكلاسات :
المتغيرات دائما تبدأ بحرف F اختصار الى Field .
و الدوال تبدأ بحرف uppercase .
يستحسن أن تستلزم بهذه المسلمات حتى يستطيع غيرك قراءة أكوادك 
إقتباس :يحصل خطا حيث اني لم أعمل Create للقائمة .. هل يجب ان اعدل الدالة Create الخاصة بالكلاس واضع فيها امر انشاء القائمة ؟
بالضبط , FPhoneNumbers عبارة عن Object .. و أي Object يجب أن يتم انشائه قبل استخدامه .
PHP كود :
type
TMyClass = class(TPersistent)
private
FAge: Integer;
FName: string;
FPhoneNumbers: TStringList;
procedure SetPhoneNumbers(const Value: TStringList);
protected
procedure AssignTo(Dest: TPersistent); override;
public
constructor Create; virtual;
destructor Destroy; override;
property Name: string read FName write FName;
property Age: Integer read FAge write FAge;
property PhoneNumbers: TStringList read FPhoneNumbers write SetPhoneNumbers;
end;
{ TMyClass }
procedure TMyClass.AssignTo(Dest: TPersistent);
var
LDst: TMyClass;
begin
if not(Dest is TMyClass) then
raise Exception.Create('Dest is not TMyClass !');
LDst := TMyClass(Dest);
LDst.FName := FName;
LDst.FAge := FAge;
LDst.FPhoneNumbers.Assign(FPhoneNumbers);
end;
constructor TMyClass.Create;
begin
FPhoneNumbers := TStringList.Create;
end;
destructor TMyClass.Destroy;
begin
FreeAndNil(FPhoneNumbers);
inherited;
end;
procedure TMyClass.SetPhoneNumbers(const Value: TStringList);
begin
if Value <> FPhoneNumbers then
FPhoneNumbers.Assign(Value);
end;
procedure TForm2.Button1Click(Sender: TObject);
var
Man1, Man2: TMyClass;
begin
Man1 := TMyClass.Create;
Man1.Name := 'Kahld';
Man1.Age := 15;
Man1.PhoneNumbers.Add('XXXXXXXXXXXX');
Man1.PhoneNumbers.Add('AAAAAAAAAAAA');
Man1.PhoneNumbers.Add('WWWWWWWWWWWW');
Man2 := TMyClass.Create;
Man2.Assign(Man1);
Edit1.Text := Man2.Name;
Edit2.Text := IntToStr(Man2.FAge);
Edit3.Text := Man2.PhoneNumbers[0]
end;
بالتوفيــــق .
Open Your Source .. Open Your Mind
المشاركات : 306
المواضيع 45
:
: 0
الإنتساب : Jul 2012
إقتباس :فكرة رائعة و صائبة أن تتعلم ال oop .. صدقني عندما تتقنها ستندم لأنك لم تتعلمها في وقت سابق
لا زلت اتذكر نصيحتك لي في احد المواضيع عندما قلت ان الـ OOP مهمه جداً..إلخ رغم اني لم اتبعها للاسف
لكن ما اجبرني على تعلم الـ OOP عندما بدأت البرمجة على C Plus Puls تحديداً على Qt Creator فهناك كان كل شيء
يتم من خلال OOP وبدون استعمالها لا استطيع برمجة برنامج جيد فاُجبرت على تعلم الـ OOP .. فانا من البداية كنت اتجنب
الإصطدم بـ OOP لني لم افهمها من المره الاولى xD
-----------------------------------
تمام كل شيء في مكانه
لكن لدي سؤال صغير ماذا يقصد بالـ الكلمات التي تأتي بعد الدوال مثل
وكذلك لماذا وضعت الدالة
PHP كود :
procedure AssignTo(Dest: TPersistent); override;
في التغليف protected ؟ هل كي يتم توريثها عندما يتم وراثه هذا الكلاس من كلاس آخر او ماذا ؟
المشاركات : 632
المواضيع 66
:
: 6
الإنتساب : Jul 2010
إقتباس :لكن لدي سؤال صغير ماذا يقصد بالـ الكلمات التي تأتي بعد الدوال مثل
virtual : تعني أن الدالة مسموح بأن يتم توريثها من الكلاس الابن
override : و تعني اعادة التوريث .
dynamic : تعمل نفس عمل virtual لكن الآلية مختلفة .
يفضل أن تستخدم virtual بدل dynamic لأن الأولى أسرع ..
سابقا عندما كانت الرام لا تتجاوز 32 مب كانوا يستخدمون dynamic لانها لا تستهلك من الرام الكثير ..لكنها بطيئة جدا مقارنة مع virtual .
الق نظرة على هذا المثال البسيط ليوضح لك الفكرة :
PHP كود :
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TBase = class(TObject)
procedure SayHi; virtual;
procedure SayGoodbye; virtual;
end;
TChildBase = class(TBase)
procedure SayHi; override;
procedure SayGoodbye;
end;
{ TBase }
procedure TBase.SayGoodbye;
begin
Writeln('The Base say goodbye :)');
end;
procedure TBase.SayHi;
begin
Writeln('The Base say hi :)');
SayGoodbye;
end;
{ TChildBase }
procedure TChildBase.SayGoodbye;
begin
Writeln('The Child say goodbye');
end;
procedure TChildBase.SayHi;
begin
inherited;
Writeln('The Child also say hi :)');
end;
var obj:TChildBase;
begin
obj:=TChildBase.Create;
obj.SayHi;
Readln;
end.
إقتباس :وكذلك لماذا وضعت الدالة
PHP كود :
procedure AssignTo(Dest: TPersistent); override;
في التغليف protected ؟ هل كي يتم توريثها عندما يتم وراثه هذا الكلاس من كلاس آخر او ماذا ؟
protected : تعني أن الدالة قابلة للنداء فقط من الكلاسات المورثة من الكلاس المصرحة بها
private : الدالة قابلة للنداء داخل ال Unit فقط .
في المثال الذي كتبته :
AssignTo : غير قابلة للنداء خارج الكلاس ..
بمعنى كود مثل هذا خاطئ :
PHP كود :
var
m,x:TMyClass;
begin
...
m.AssignTo(x); //error!
...
end;
ألق نظرة على هذا المثال :
PHP كود :
unit Unit2;
interface
type
TBase = class(TObject)
procedure SayHi; virtual;
procedure SayGoodbye; virtual;
protected
procedure LeaveMeAlone;
private
procedure DoSomething;
end;
TChildBase = class(TBase)
procedure SayHi; override;
procedure SayGoodbye;
end;
implementation
{ TBase }
procedure TBase.DoSomething;
begin
Writeln('i am doing something ..');
end;
procedure TBase.LeaveMeAlone;
begin
Writeln('??????');
end;
procedure TBase.SayGoodbye;
begin
Writeln('The Base say goodbye :)');
end;
procedure TBase.SayHi;
begin
Writeln('The Base say hi :)');
SayGoodbye;
end;
{ TChildBase }
procedure TChildBase.SayGoodbye;
begin
Writeln('The Child say goodbye');
end;
procedure TChildBase.SayHi;
begin
inherited;
Writeln('The Child also say hi :)');
end;
end.
PHP كود :
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Unit2 in 'Unit2.pas';
type
TMyClass = class(TChildBase)
procedure DoSomeWork;
end;
var
obj: TChildBase;
{ TMyClass }
procedure TMyClass.DoSomeWork;
begin
LeaveMeAlone;
DoSomething; // error !
end;
begin
obj := TChildBase.Create;
obj.SayHi;
Readln;
end.
Open Your Source .. Open Your Mind
المشاركات : 29
المواضيع 3
:
: 0
الإنتساب : Mar 2011
SMP3 كتب :
فكرة رائعة و صائبة أن تتعلم ال oop .. صدقني عندما تتقنها ستندم لأنك لم تتعلمها في وقت سابق :eek:
دلني على مرجع مناسب للمبتدئين لتعلم oop بإستخدام دلفي.
المشاركات : 306
المواضيع 45
:
: 0
الإنتساب : Jul 2012
بالنسبة لي فهذا هو الكتاب الذي تعلمت منه الـ OOP في دلفي
من تأليف "عروة علي عيسى"
http://www.delphi4arab.net/forum/showthread.php?tid=97
المشاركات : 632
المواضيع 66
:
: 6
الإنتساب : Jul 2010
أفضل و سيلة هي الاطلاع على كلاسات دلفي .
Open Your Source .. Open Your Mind
المشاركات : 306
المواضيع 45
:
: 0
الإنتساب : Jul 2012
إقتباس :أفضل و سيلة هي الاطلاع على كلاسات دلفي
+1
فلا يوجد كتاب يتكلم عن كل ما تحتويه دلفي 100% على حد علمي
بالمناسبة اخي smp3 هل لك ان تذكر الطريقة المتبعه بإستخدام rtti يبدو اني ساحتاجها قريباً
المشاركات : 632
المواضيع 66
:
: 6
الإنتساب : Jul 2010
ALmuhhnad كتب :+1
فلا يوجد كتاب يتكلم عن كل ما تحتويه دلفي 100% على حد علمي
بالمناسبة اخي smp3 هل لك ان تذكر الطريقة المتبعه بإستخدام rtti يبدو اني ساحتاجها قريباً
ستحتاج الى أن تكون على علم بالتقنيات التالية :
[COLOR="Red"]- Generics & Collections
- OOP
- RTTI
[/COLOR]
خذلك أولا قهوة ثقيلة ..
ثم توكل على الله ..
ثم اطلع على هذا الرابط :
كود :
http://delphihaven.wordpress.com/2011/06/09/object-cloning-using-rtti/
بعد ان تتطلع على الرابط .. يمكنك البدأ في دراسة طريقة عمل Object Inspector
كود :
http://www.delphi4arab.net/forum/showthread.php?tid=11010
المكون مبني بالكامل بال RTTI & Generics و بالطبع تصميم بال OOP .
Open Your Source .. Open Your Mind
المشاركات : 358
المواضيع 34
:
: 2
الإنتساب : Nov 2008
السلام عليكم
عندما تقوم بانشاء اوبجكت من كلاس فان هدا الأبجكت يشغل مساحة من الداكرة ولنسخ الأوبجكت يكفي معرفة المساحة التي يشغلها انظر المثال كتبته بشكل سريع
PHP كود :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Tmycls = class
private
public
FName : string;
procedure clonCedsit(s: string);
end;
var
Form1: TForm1;
implementation
procedure TMycls.clonCedsit(s: string);
begin
FName := s;
end;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var obj1, obj2 : Tmycls;
begin
obj1 := Tmycls.Create();
obj2 := Tmycls.Create();
obj1.clonCedsit('jamalcoder');
ShowMessage(IntToStr(obj1.InstanceSize));
CopyMemory(Pointer(obj2), Pointer(obj1), obj1.InstanceSize);
Self.Caption:= obj2.FName;
obj1.Free;
obj2.Free;
end;
end.
لا اله الا أنت سبحانك اني كنت من الضالمين