إستفسار حول OOP Interface in Delphi ؟
#1
السلام عليكم ورحمة الله تعالى وبركاته

قمت بكتابة هذه الوحدة و الغرض منها هو تطبيق لفهم :
1- كيف يتم إنشاء interface في الدلفي
2- عمل class تقوم بوراثة class اخرى + تقوم ب implementation للـ Interface

قمت بكتابة هذا الكود لكن يوجد خطأ في هذا السطر : 
كود :
TApp = class(TClassA, IMyInterface)

وهذا نص الخطأ الذي يظهره الـ compiler :

كود :
[dcc32 Error] uMyUnit.pas(21): E2291 Missing implementation of interface method IInterface.QueryInterface
[dcc32 Error] uMyUnit.pas(21): E2291 Missing implementation of interface method IInterface._AddRef
[dcc32 Error] uMyUnit.pas(21): E2291 Missing implementation of interface method IInterface._Release
[dcc32 Fatal Error] WorkOnInterface.dpr(6): F2063 Could not compile used unit 'uMyUnit.pas'
Failed

الكود الخاص بالـ unit الت صممتها :

كود :
unit uMyUnit;

interface

type

  IMyInterface = Interface(IInterface)
     function GetAdd(pX , pY: integer) : integer;
  End;

  TClassA = class(TObject)
     private
      FX : integer;
      FY : integer;
    public
      constructor Create(pX, pY : integer);
      function GetName: String;
      function GetProduit : integer;
  end;

  TApp = class(TClassA, IMyInterface)
    public
      constructor Create(pX, pY: integer);
      function GetAdd(pX , pY: integer) : integer;
  end;

implementation

{ TClassA }

constructor TClassA.Create(pX, pY: integer);
begin
  FX:= pX;
  FY:= pY;
end;

function TClassA.GetName: String;
begin
  Result := 'TClassA';
end;

function TClassA.GetProduit: integer;
begin
  Result := FX * FY;
end;

{ TApp }

constructor TApp.Create(pX, pY: integer);
begin
  inherited Create(pX, pY);
end;

function TApp.GetAdd(pX, pY: integer): integer;
begin
  Result := FX + FY;
end;

end.
الرد
#2
كل Interface تنحدر من IInterface والتي تحتوي على ٣ اجراءات يجب عمل implementation لهم، لذا عليك التوريث من TInterfacedObject بدل الكلاس TClassA, ويفضل ان تفصل ما في TClassA من اجراءات ووضعها في Interface, لأنه لا يوجد الوراثة المتعددة في الدلفي، ولا يمكن وراثة كلاس اخرى مع TInterfacedObject.

الكلاس TInterfacedObject فيها Implementation للثلاث اجراءات التي حدث لك مشكل معها.
الرد
#3
بارك الله فيك اخي سفيان على الرد (كم تسعدنا بردودك القيمة)

نعم كما ذكرت, سبب المشكلة هو أنه لم أقم بعمل Implementation لـ 3 methodes موجودة  في Interface المسمات IInterface والتي قمت بعمل وراثة منها لـ interface الخاصة بي التي سميتها IMyInterface.

وهذا الكود الموضح للعملية : 
كود :
IMyInterface = Interface(IInterface)
     function GetAdd(pX , pY: integer) : integer;
  End;

إذا في هذه الحالة اصبحت IMyInterface تحتوي على 4 methodes واحدة التي كتبتها GetAdd و 3 methodes جاءؤ عن طريقة الوراثة من [size=small]IInterface.[/size]

في هذه الحالة ايي كلاس تقوم بعمل Implementation لل IMyInterface يجب عليها تعريف 4 methodes يعني كتابة body الخاص بهم.

وعليه الحل رقم 1 يكون كما يلي :

كود :
unit uMyUnit;

interface

type

  IMyInterface = Interface(IInterface)
     function GetAdd(pX , pY: integer) : integer;
  End;

  TClassA = class(TObject)
     private
      FX : integer;
      FY : integer;
    public
      constructor Create(pX, pY : integer);
      function GetName: String;
      function GetProduit : integer;
  end;

  TApp = class(TClassA ,IMyInterface)
    public
      constructor Create(pX, pY: integer);

      function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
      function _AddRef: Integer; stdcall;
      function _Release: Integer; stdcall;

      function GetAdd(pX , pY: integer) : integer;
  end;

implementation

{ TClassA }

constructor TClassA.Create(pX, pY: integer);
begin
  FX:= pX;
  FY:= pY;
end;

function TClassA.GetName: String;
begin
  Result := 'TClassA';
end;

function TClassA.GetProduit: integer;
begin
  Result := FX * FY;
end;

{ TApp }

constructor TApp.Create(pX, pY: integer);
begin
  inherited Create(pX, pY);
end;

function TApp.GetAdd(pX, pY: integer): integer;
begin
  Result := FX + FY;
end;

function TApp.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if GetInterface(IID, Obj) then
    Result:= S_OK
  else
    Result:= E_NOINTERFACE;
end;

function TApp._AddRef: Integer;
begin
  Result:= -1;
end;

function TApp._Release: Integer;
begin
  Result:= -1;
end;

end.

والحل رقم 2 يكون بستغلال الـ Class TInterfacedObject التي قامت مسبقا بعمل implementation لـ IInterface :
لذلك يجب تغيير هذا التعريف :
كود :
TClassA = class(TObject)
 بهذا : 
كود :
TClassA = class(TInterfacedObject)

ويبقى كل شيء على ماهو عليه.
الكود الكامل للحل رقم 2 :

كود :
unit uMyUnit;

interface

type

  IMyInterface = Interface(IInterface)
     function GetAdd(pX , pY: integer) : integer;
  End;

  TClassA = class(TInterfacedObject)
     private
      FX : integer;
      FY : integer;
    public
      constructor Create(pX, pY : integer);
      function GetName: String;
      function GetProduit : integer;
  end;

  TApp = class(TClassA ,IMyInterface)
    public
      constructor Create(pX, pY: integer);
      function GetAdd(pX , pY: integer) : integer;
  end;

implementation

{ TClassA }

constructor TClassA.Create(pX, pY: integer);
begin
  FX:= pX;
  FY:= pY;
end;

function TClassA.GetName: String;
begin
  Result := 'TClassA';
end;

function TClassA.GetProduit: integer;
begin
  Result := FX * FY;
end;

{ TApp }

constructor TApp.Create(pX, pY: integer);
begin
  inherited Create(pX, pY);
end;

function TApp.GetAdd(pX, pY: integer): integer;
begin
  Result := FX + FY;
end;

end.

ملاحظة : الحل رقم 2 إستنتجته لوحدي من التجارب التي اجريتها واره افضل من الحل الأول , ما تعليقكم عليه؟؟
الرد
#4
ألاحظ أن الأخ صفيان متخصص في دلفي

* لما درسنا سابقا كانوا يقولون لنا يجب تحرير الذاكرة حتى لا تمتلأ الذاكرة و يصبح الجهاز بطيء ، ويجب تفادي التكرار في قواعد البيانات لتفادي الحجم الكبير

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

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

على العكس من ذلك إدارة الذاكرة مهمة للغاية ، على الرغم من توفر أجهزة صاروخية ، و حجم الملف التنفيذي لا علاقة له بإستهلاك الذاكرة في حال عرف المبرمج كيف يقوم بإنشاء الكائنات و المكونات و تحريرها عند الحاجة ، مثال ذلك في برنامج يحتوي الكثير من النماذج forms ، من غير المعقول إنشائها تلقائيا عند بدء البرنامج ، تستطيع الإستغناء على العمل الروتيني للبرمجة في دلفي ، و هذا سهل و بسيط و يعد من قبيل تمكن المبرمج من التحكم الكامل في تسيير خطوات برنامجه.
[-] كل من 2 users say قال شكرا ل seddik_xp على المشاركة المفيدة
  • larbiparadox, MasteranyOne
الرد


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


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