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

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

Threaded View

پست قبلی پست قبلی   پست بعدی پست بعدی
  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 در 15:22 عصر

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

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

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

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