نمایش نتایج 1 تا 3 از 3

نام تاپیک: حل مشکل Circular unit reference توسط Class Helper ها

  1. #1

    Post حل مشکل Circular unit reference توسط Class Helper ها

    سلام ،

    در اکثر موارد وقتي تصميم ميگيريم که برنامه رو به کلاس هاي مجزا تقسيم کنيم و هر کلاس رو در کتابخانه اي جدا پياده کنيم در بخش هايي نياز ميشه که از کلاسي در کلاس ديگه استفاده بشه ، در اين مواقع بارها شده که با پيغاه خطا Circular unit reference مواجه شديد ، اين پيغام زماني مشاهده ميشه که از دو کتابخانه داخل يکديگر استفاده کرده باشيم ، مثلا :

    unit Unit1;

    interface

    uses Unit2;

    implementation

    end.


    unit Unit1;

    interface

    uses Unit1;

    implementation

    end.


    يکي از راه حل ها در اين مواقع استفاده از Class Helper ها هست ( البته راه حل هايي مثل جدا کردن ساختارهايي که زياد استفاده ميشن در يک کتابخانه جداگانه يا طراحي مجدد و اصولي کلاسي که نوشته شده قبل از اين راه حل پيشنهاد ميشه ! )

    خوب فرض کنيد کتابخانه هايي مثل اين :

    unit Dog;

    interface

    type
    TDog = class
    Name: String;
    end;

    implementation

    end.


    و اين داريم :

    unit Master;

    interface

    type
    TMaster = class
    Name: String;
    end;

    implementation

    end.


    خوب حالا تو برنامه براي استفاده از اين دو برادر عزيز ازشون نمونه سازي ميکنيم :

    uses
    Dog, Master;

    var
    Dog: TDog;
    Master: TMaster;
    begin
    Dog := TDog.Create;
    Master := TMaster.Create;
    try
    Dog.Name := 'Bobby';
    Master.Name := 'Joe';
    finally
    Dog.Free;
    Master.Free;
    end;
    end;


    حالا تصميم ميگيريم به کلاس TDog متدي با نام Master اضافه کنيم ( از نوع TMaster ) که مشخصات مربي اين سگ رو نگهداري کنه :

    unit Dog;

    interface

    uses Master;

    type
    TDog = class
    Name: String;
    Master: TMaster;
    end;

    implementation

    end.


    تا اينجا همه چي آرومه ، من چقدر خوشحالم ...

    خوب حالا نياز داريم تو کلاس مربي هم يک متد با نام Dog داشته باشيم ( از نوع TDog ) که مشخصات سگ اين مربي رو نگهداري کنه ، خوب کد زير رو مينويسم :

    unit Master;

    interface

    uses
    Dog;

    type
    TMaster = class
    Name: String;
    Dog: TDog;
    end;

    implementation

    end.


    خوب ؟! همونطور که میبینید با پیغام خطا Circular unit reference عملیات کامپایل متوقف میشه .

    اولین چیزی که به ذهن میرسه این هست که متد Dog رو از نوع TObject در نظر بگیریم ، یعنی :

    unit Master;

    interface

    type
    TMaster = class
    Name: String;
    Dog: TObject;
    end;

    implementation

    end.


    کد زیر بدون مشکل کامپایل میشه ولی بدیش این هست که برای هر کاری باید Typecast های متعددی انجام بدید ، مثلا برای نمایش نام مربی یک سگ :

    Writeln(TDog(Master.Dog).Name);


    و حالا راه حلی با استفاده از Class Helper ها ؛

    اوین قدم تعریف Dog به صورت یک فیلد Protected در کلاس TMaster هست ، یعنی کلاس TMaster رو به صورت زیر مینویسم :

    unit Master;

    interface

    type
    TMaster = class
    protected
    fDog: TObject;
    public
    Name: String;
    end;

    implementation

    end.


    حالا کافیه به وسیله Class Helper ها یک پراپرتی برای کلاس TMaster بنویسیم تا شئ Dog رو به صورت یک نمونه از کلاس TDog به ما تحویل بده :

    unit MasterClassHelper;

    uses
    Dog, Master;

    type
    TMasterClassHelper = class helper for TMaster
    private
    procedure SetDog(Value: TDog);
    function GetDog: TDog;
    public
    property Dog: TDog read GetDog write SetDog;
    end;

    function TMasterClassHelper.GetDog: TDog;
    begin
    Result := TDog(FDog); // cast the TObject(FDog) to TDog!
    end;

    procedure TMasterClassHelper.SetDog(Value: TDog);
    begin
    FDog := Value;
    end;


    و حالا تو برنامه خیلی راحت بدون هیچ Typecast ی میتونیم از کلاس TMaster و TDog استفاده کنیم :

      Writeln(Master.Dog.Name);
    Writeln(Dog.Master.Name);


    حتی :
    Writeln(Dog.Master.Dog.Master.Dog.Master.Dog.Name)  ;


    آقا جنبه داشته باش !

    همچنین با use کردن کتابخانه MasterClassHelper در کتابخانه Master علاوه بر کلاس TMaster میتونید به کلاس TDog هم دسترسی داشته باشید :

    Unit unit1;

    type
    TMaster = class
    protected
    FDog: TObject;
    public
    Name: String;
    procedure RenameDog;
    end;

    implementation

    uses
    MasterClassHelper;

    procedure TMaster.RenameDog;
    begin
    Dog.Name := 'Buddy';
    end;


    در آخر اگر مجبور به استفاده از این مطلب شدید بهتره یه جفت کتاب در مورد اصول برنامه نویسی شئ گرا بخونید و تجدید نظری در مورد طراحی کلاس هاتون بکنید .

    یا حق .
    آخرین ویرایش به وسیله Felony : یک شنبه 30 مهر 1391 در 16:22 عصر

  2. #2

    نقل قول: حل مشکل Circular unit reference

    سلام

    مقاله رو هنوز کامل نخوندم ولی یک راه حل خیلی ساده هم برای رفع خطای Circular unit reference وجود داره و اون هم اینه که یکی از یونیت ها رو در قسمت Uses مربوط به Interface بنویسیم و دیگری رو در قسمت Uses مربوط به Implementation. البته این راه حل زیاد جالب نیست ولی در برخی موارد مثل مسکن عمل می کنه.
    مثال:

    کد مربوط به یونیت A:
    unit A;

    Interface
    uses
    B;
    //...

    implementation

    //...

    end.


    کد مربوط به یونیت B:
    unit B;

    Interface

    //...

    implementation

    uses
    A;
    //...

    end.



    موفق باشید...

  3. #3

    نقل قول: حل مشکل Circular unit reference توسط Class Helper ها

    در این صورت نمیتونیم از کلاسی که مثلا در کتابخانه اولی تعریف کردیم در کلاس کتابخانه دوم به عنوان Data Type یک فیلد استفاده کنیم ، مثلا :

    کتابخانه اول :

    unit Unit2;

    interface

    uses Unit3;

    type
    TDog = class
    Name: String;
    Master: TMaster;
    end;

    implementation

    end.


    کتابخانه دوم :

    unit Unit3;

    interface

    implementation

    uses
    unit2;

    type
    TMaster = class
    protected
    fDog: TDog;
    public
    Name: String;
    end;

    end.


    Scope تعریف کلاس ها باعث میشه که همدیگرو نتونن ببینن .

تاپیک های مشابه

  1. مشکل در Add Reference
    نوشته شده توسط Happy_davood در بخش C#‎‎
    پاسخ: 0
    آخرین پست: شنبه 17 تیر 1391, 18:37 عصر
  2. مشکل در Add Reference
    نوشته شده توسط mahdi68 در بخش طراحی و ساخت بازی‌های کامپیوتری
    پاسخ: 1
    آخرین پست: دوشنبه 22 آذر 1389, 13:16 عصر
  3. سوال: مشکل در web references
    نوشته شده توسط hamid_ar84 در بخش ASP.NET Web Forms
    پاسخ: 2
    آخرین پست: دوشنبه 01 شهریور 1389, 16:46 عصر
  4. مشکل در Class reference
    نوشته شده توسط JalaliMehr در بخش مباحث عمومی دلفی و پاسکال
    پاسخ: 0
    آخرین پست: شنبه 29 خرداد 1389, 12:03 عصر
  5. خطای Circular Unit
    نوشته شده توسط JalaliMehr در بخش مباحث عمومی دلفی و پاسکال
    پاسخ: 6
    آخرین پست: جمعه 07 خرداد 1389, 02:48 صبح

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •