كيف يتم نسخ كلاس إلى آخر ؟
#11
إقتباس :ستحتاج الى أن تكون على علم بالتقنيات التالية :
- Generics & Collections
- OOP
- RTTI

خذلك أولا قهوة ثقيلة ..
ثم توكل على الله ..
ثم اطلع على هذا الرابط :
هذه تريد ليلة من ليال الشتاء الطويلة Tongue
الف شكر لك وعلى تعاونك Smile

--------------------------------------
إقتباس :السلام عليكم

عندما تقوم بانشاء اوبجكت من كلاس فان هدا الأبجكت يشغل مساحة من الداكرة ولنسخ الأوبجكت يكفي معرفة المساحة التي يشغلها انظر المثال كتبته بشكل سريع
فعلاً هذه كانت نظرتي وتوقعي للامر
لكن فكرت بالامر أكثر وتذكرت ان وبجكت يمكن ان يحتوي على على اوبجكت آخر

مثال عملي :
PHP كود :
type
  TMyClass 
= Class
    
Name: string;                             // in your way .. this value will be copied fine because it's value 
    
Age: integer;                             // same here
    
Address: string;    

    
PhoneNumbers: TStringList; // this will be the problem .. when you copy it you just copy the pointer for it 
                                                         // so if the obj1 Freed the obj2 will lose its PhoneNumbers pointer because it
                                                         // belong to obj1 
  
end; 

فإذا اردت ان اقوم بنسخ حقيقي سيتطلب الامر ان اعرف عنوان الوبجكت الذي أريـ ـد نسخه ثم اقوم بنسخ للذاكرة الاوبجكت
وبعد ذلك اتأكد هل البيانات التي تم نسخها هي قيم(Values) ام مؤشرات(Pointers) إذا كانت مؤشرات
اقوم بنسخ المكان الذي يشير إليه هذا المؤشر ثم أتاكد من البيانات التي نسختها هل تشير إلى مؤشرات آخرى ام لا ...وعلى هذا المنوال الغير محكم فربما تحدث اخطا ..إلخ

طبعاً كل هذه هي توقعات نظرية ولم اطبق اين منها
الرد
#12
فعلاً كما توقعت Smile

انظر لهذا المثال الذي قمت بتطبيق فكرتك فيه

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;

  
TMyClass = class
    private
    public
      
Name: String;
      
Age: Integer;
      
PhoneNumbers: TStringList;    
      
constructor Create; virtual;
      
destructor Destroy; override;
  
end;

var
  
Form1: TForm1;
  
obj1, obj2: TMyClass;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  obj1 
:= TMyClass.Create;
  
obj1.Name := 'Ali';
  
obj1.Age := 15;
  
obj1.PhoneNumbers.Add('XXXXXXXXXXXXXXXXX');
  
ShowMessage( Format('Pointer for obj1.PhoneNumbers is : %p', [Pointer(obj1.PhoneNumbers)])
    + 
'                  fist number value is : ' + obj1.PhoneNumbers.Strings[0]);

  
obj2 := TMyClass.Create;

  
ShowMessage(IntToStr(obj1.InstanceSize));
  
CopyMemory(Pointer(obj2), Pointer(obj1), obj1.InstanceSize);

  
obj1.Free;

// here you will get the error.. Because there is no pointer anymore
  
ShowMessage('fist number value is : ' + obj2.PhoneNumbers.Strings[0]); 
  
obj2.Free;
end;

{ 
TMyClass }

constructor TMyClass.Create;
begin
  PhoneNumbers 
:= TStringList.Create;
end;

destructor TMyClass.Destroy;
begin
  FreeAndNil
(PhoneNumbers);
  
inherited;
end;

end. 
الرد
#13
me_delphi كتب :السلام عليكم

عندما تقوم بانشاء اوبجكت من كلاس فان هدا الأبجكت يشغل مساحة من الداكرة ولنسخ الأوبجكت يكفي معرفة المساحة التي يشغلها انظر المثال كتبته بشكل سريع

يا ريت الطريقة كانت بتلك البساطة ..

جرب هذا الكود :

PHP كود :
var
  
obj1, obj2: Tmycls;
begin
  obj1 
:= Tmycls.Create();
  
obj2 := Tmycls.Create();
  
obj1.clonCedsit('jamalcoder');
  
obj1.FName := 'test';
  
CopyMemory(Pointer(obj2), Pointer(obj1), obj1.InstanceSize);
  
obj1.FName :='nil';
  
Self.Caption := obj2.FName;  // failed !
  
obj1.Free;
  
obj2.Free;
end; 
Open Your Source .. Open Your Mind
الرد
#14
نعم الأمر معقد..انا لم أقم بالتجريب اتبعت المنطق فقط لكن العملية تتطلب دراسة و فهم

المهم هدا الكود لم يعمل لنه تم تعديل الأوبجكت 1 أي يجب ان تكون هده العملية هي الأخيرة

إقتباس :copymemory(pointer(obj2), pointer(obj1), obj1.instancesize);

والا لن يكون الأوبجكت 1 و 2 متساويين

أي يجب ان ننتهي من جميع التعديلات قبل أن نقوم بعملية النسخ
لا اله الا أنت سبحانك اني كنت من الضالمين
الرد
#15
نفس النتيجة
عندما اعدل الـ
obj1.PhoneNumbers
سيتم تغيير قيمة الـ obj2.PhoneNumbers
PHP كود :
obj1 := TMyClass.Create;
  
obj1.PhoneNumbers.strings[0] := '000000';

  
obj2 := TMyClass.Create;
   
copymemory(pointer(obj2), pointer(obj1), obj1.instancesize); 
  
  
showMessage(obj1.PhoneNumbers.strings[0]);   { Result will be : 000000 }
  
showMessage(obj2.PhoneNumbers.strings[0]);   { Result will be : 000000 }

  
obj1.PhoneNumbers.strings[0] := '555555';

  
showMessage(obj1.PhoneNumbers.strings[0]);   { Result will be : 555555}
  
showMessage(obj2.PhoneNumbers.strings[0]);   { Result will be : 555555}
  
// so obj2 use same TStringList that belong to obj1 .. if you change PhoneNumbers
  // in obj1 it will change in obj2.. same if you change obj2.PhoneNumbers it will change
  // in obj1 

والمطلوب هو نسخ الكلاس أي يكون الـ obj2 يملك مساحته الخاصة بالذاكرة والقيم الخاصة به بالذاكرة حيث انه ليس مرتبط بالـ obj1 كلياً
الرد


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


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم