PDA

View Full Version : خطای Circular Unit



JalaliMehr
پنج شنبه 06 خرداد 1389, 17:02 عصر
سلام به همه دوستان
یک سوالی در مورد استفاده از یونیت ها خطای Circular unit داشتم.
من دو تا یونیت با نام A و B دارم.
در A کلاسی با نام CA دار و در B کلاسی به نام CB.
در کلاس CA کلاس CB بعنوان یک خصیصه است
در کلاس CB کلاس CA بعنوان یک خصیصه است
پس من مجبور هستم در قسمت interface هر دو یونیت اون یکی رو در قسمت Uses اضافه کنم که اون خطای بالا رو دریافت می کنم.
راه حل رو اگر دوستان لطف کنند ممنون میشم

Mahmood_M
پنج شنبه 06 خرداد 1389, 17:16 عصر
این مورد قبلا در سایت مطرح شده (http://barnamenevis.org/forum/showthread.php?t=215529) ، جواب داده شده رو بخونید ، اگر باز مشکلی وجود داشت مطرح کنید ...

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

JalaliMehr
پنج شنبه 06 خرداد 1389, 17:44 عصر
ممنون از توجه شما.
اون تاپیک رو خوندم مربوط می شد به استفاده متقابل دو تا فرم و رفع خطای Circular ولی مورد رو که من بیان کردم اینه که هر دو Class مجبورند در قسمت Interface از همدیگر استفاده کنن .
از دوستان خواهش میکنم جواب بدین

vcldeveloper
پنج شنبه 06 خرداد 1389, 18:18 عصر
حل این مدل مشکلات Circular unit referencing بدون اینکه دقیقا مشخص باشه که کلاس های شما چه ارتباطاتی با هم دارند، و هدف از آنها چی هست، خیلی سخته. به طور کلی، وقتی در طراحی به همچین حالتی می رسید، معمولا یک جا در طراحی مشکل داشتید، و برای رفع آن هم با بررسی طراحی کلاس ها، سعی میشه طراحی بهتری که منجر به Circular unit نشه، ارائه بشه.

ساده ترین حالت که در واقع راه حل نیست، بلکه Workaround هست، اینه که شما هر دو کلاس رو داخل یک یونیت تعریف کنید. در هر حال، به اطلاعات بیشتری درباره کلاس های شما نیاز هست.

در ضمن، به نظر میاد چند ID در سایت ایجاد کردید؟

JalaliMehr
پنج شنبه 06 خرداد 1389, 20:46 عصر
من دو تا کلاس به شکل زیر تعریف کردم که باعث خطا میشه. این یه مثاله ولی محتوای unit های واقعی شامل چندین هزار خط کد که کنترل آن سخت شده است برای همین می خوام کلاسها رو مجزا کنم

Unit A

unit A;

interface
uses B;
type
TPattern = class
private
FNetwork:TNetwork;
public
constructor create(aNetwork:TNetwork);
end;

implementation

{$R *.dfm}

{ TPattern }

constructor TPattern.create(aNetwork: TNetwork);
begin
FNetwork:=ANetwork;
end;
end.



Unit B

unit B;

interface
uses A; // Error Here : Circular Unit Reference
type
TNetwork = class
private
Patterns:array of TPattern;
public
constructor create(aCount:Integer);
end;

implementation

{$R *.dfm}

{ TNetwork }

constructor TNetwork.create(aCount: Integer);
var
I: Integer;
begin
SetLength(Patterns,aCount);
for I := 0 to aCount - 1 do
Patterns[i]:=TPattern.create(Self);
end;

end.

SAASTN
پنج شنبه 06 خرداد 1389, 21:22 عصر
یه راه اینه که unitb رو به روش زیر پیاده سازی کنی:

unit B;

interface

type
TNetwork = class
private
Patterns:array of TObject;
public
constructor create(aCount:Integer);
end;

implementation

uses A;
{$R *.dfm}

{ TNetwork }

constructor TNetwork.create(aCount: Integer);
var
I: Integer;
begin
SetLength(Patterns,aCount);
for I := 0 to aCount - 1 do
Patterns[i]:=TPattern.create(Self);
end;

end.

توجه داشته باش که اگه جایی بخوای از Pattern استفاده کنی، مثلا برای اون تابعی به اسم Method1 نوشته باشی، باید به شکل زیر عمل کنی:

(Patterns[I] as TPattern).Method1;
// or
TPattern(Patterns[I].Method1;

vcldeveloper
جمعه 07 خرداد 1389, 01:48 صبح
من دو تا کلاس به شکل زیر تعریف کردم که باعث خطا میشه. این یه مثاله ولی محتوای unit های واقعی شامل چندین هزار خط کد که کنترل آن سخت شده است برای همین می خوام کلاسها رو مجزا کنم
این تقریبا همان توضیحات قبلی هست، فقط بهش مثال اضافه شده. من منظورم ارتباط معنایی این کلاس ها با هم بود، نه اینکه در چه قالبی به هم ارجاع میدند.

در هر حال، یک راهش اینه که شما دو کلاس را با هم در یک یونیت تعریف کنید، با این تفاوت که یکی از کلاس ها را کوچک کنید، و به عنوان کلاس پایه برای یک کلاس فرزند از آن استفاده کنید. مثلا کلاس TNetwork در یونیت A باشه، ولی فقط بخشی از امکانات اولیه آن که مورد نیاز TPattern هست، در این کلاس تعریف بشه، و در یونیت B یک کلاس جدید (مثلا TChildNetwork) hc از TNetwork مشتق بشه، و بخش عمده ایی از کدهای کلاس TNetwork به این کلاس جدید منتقل بشه. اینطوری کدها بین دو یونیت A و B تقسیم میشند.

راه دیگه اینه که از Interface استفاده کنید؛ مثلا قابلیت هایی که باید TNetwork در اختیار TPattern قراره بده را در قالب یک Interface تعریف کنید، و این Interface را توسط کلاس TNetwork پیاده سازی کنید. در این حالت، چون Interface در یونیت A تعریف شده، کلاس TPattern میتونه از آن استفاده کنه. کلاسی هم که آن Interface را پیاده سازی کرده، میتونه در هر یونیتی باشه.

راه های دیگه هم ممکنه وجود داشته باشه، ولی باید دید این دو کلاس چه کارکردی دارند، و ارتباط معنایی شان با هم چگونه هست، تا بشه مشخص کرد چه چیزهایی از این دو کلاس را می توان در قالب کلاس ها یا Interfaceهای جدید تعریف کرد.