m-khorsandi
پنج شنبه 10 خرداد 1386, 16:54 عصر
تفاوت بین Hard Cast و AS Cast در دلفی
در دلفی از کلمهی کلیدی AS برای تبدیل یک شیی(یا Interface) از یک نوع به نوعی دیگر استفاده میشود. برای مثال اگر کلاس TDeveloper از کلاس TPerson به صورت زیر مشتق شده باشد:
Type TDeveloper = class(TPerson)
میتوانید در حالتی امن یک نمونه از نوع TDeveloper (مثلاً aDeveloper) را به TPerson تبدیل کنید به صورت زیر:
aDeveloper as TPerson
این نوع تبدیل، as-cast نامیده میشود.
البته ما بیشتر تبدیلهایی که به صورت hard-cast استفاده میشود را به کار میبریم:
TPerson(aDeveloper)
چه تفاوتی بین hard-cast و as-cast وجود دارد؟
موقعی که چندین کنترل در یک رویداد مشترک میشوند، برای مثال یک button و یک menu item (در رویداد OnClick)، به شکل مناسبی از پارامتر Sender برای شناسایی کنترلی که واقعاً باعث اجرای این رویداد شده، استفاده میکنید.
begin
if Sender is TButton then
begin
//do something if the button was clicked
end;
if Sender is TMenuItem then
begin
//do something if the menu item was clicked
end;
end;
با استفاده از کلمهی کلیدی is میتوانید نوع شیی از یک کلاس را در زمان اجرا بررسی کنید. "Sender is TButton" چک میکند که آیا پارامتر Sender یک TButton یا نوعی مشتق شده از TButton هست؟ . بعد از انجام عمل "چک" ، میتوانید شیء را به یک نوعی که نیاز دارید تبدیل کنید.
با hard-cast، به کامپایلر میگوئید که میدانید در انتظار چه شیی هستید. به همین خاطر hard-cast نا امن هست. برای دلفی جالب نخواهد بود اگر که یک نمونه از TEdit را به TButton با استفاده از hard-cast تبدیل کنید، مانند مثال زیر:
TButton(Edit1).Caption := 'junk code';
آیا این کد کار خواهد کرد؟ بله، کار خواهد کرد! با اینکه کلاس TEdit اصلاً ویژگی به نام Caption ندارد، اما تبدیل یک editbox به یک button، سپس تغییر ویژگی Caption آن button که نتیجهی آن، تغییر دادن ویژگی Text از شیء Edit1 خواهد بود. با استفاده از hard-cast میتوانید چنین تبدیلی انجام دهید.
از طرف دیگر، تبدیل امن as-cast باعث بوجود آمدن خطای EInvalidCast در این حالت خواهد شد، یعنی اگر به شکل زیر سعی در تبدیل عبارتی داشته باشید، با خطا مواجه میشوید :
//raises "Invalid Type Cast"
(Edit1 as TButton).Caption := 'junk code';
پیاده سازی Hard-Cast امن با استفاده از Is
غالب اوقات چنین کدی در دلفی پیدا خواهید کرد:
if Sender is TButton then
begin
TButton(Sender).DoSomething;
end;
در مثال بالا، با ترکیب عملگر is با hard-cast نا امن، یک تبدیل از نوع hard-cast امن خواهیم داشت.
بطو کلی شما میبایست از کد بالا استفاده کنید و نه عملگر is و در ادامهی آن as-cast، چونکه as-cast فقط زمان را مصرف میکند و مقدار زیادی سربار برای برنامه دارد، به این دلیل که کامپایلر ناگزیر به پیمودن زنجیر وار وراثت در RTL برای یافتن کلاس مشخصی ست تا بتواند شئ را به آن تبدیل کند و این زمانبر هست. فرض کنید میخواهید چندین بار کلاسی که دهمین وارث کلاس پدر خود هست را با AS-Cast تبدیل کنید، هربار ساختار سلسه مراتبی تا رسیدن به کلاسی که متد مورد نظر را داشته باشد طی میشود، حال ببینید چه سرباری میتواند برای برنامهی شما داشته باشد!؟ (به تصویر زیر دقت کنید). توسط کد بالا شما ابتدا بررسی میکنید که آیا Sender از نوع TButton هست یا خیر، و سپس با تبدیل (از نوع Hard Cast) میتوانید متد DoSomething را اجرا کنید.
http://img.majidonline.com/pic/91819/img1.jpg
فایل PDF همین مقاله را از لینک زیر میتوانید دریافت کنید:
در دلفی از کلمهی کلیدی AS برای تبدیل یک شیی(یا Interface) از یک نوع به نوعی دیگر استفاده میشود. برای مثال اگر کلاس TDeveloper از کلاس TPerson به صورت زیر مشتق شده باشد:
Type TDeveloper = class(TPerson)
میتوانید در حالتی امن یک نمونه از نوع TDeveloper (مثلاً aDeveloper) را به TPerson تبدیل کنید به صورت زیر:
aDeveloper as TPerson
این نوع تبدیل، as-cast نامیده میشود.
البته ما بیشتر تبدیلهایی که به صورت hard-cast استفاده میشود را به کار میبریم:
TPerson(aDeveloper)
چه تفاوتی بین hard-cast و as-cast وجود دارد؟
موقعی که چندین کنترل در یک رویداد مشترک میشوند، برای مثال یک button و یک menu item (در رویداد OnClick)، به شکل مناسبی از پارامتر Sender برای شناسایی کنترلی که واقعاً باعث اجرای این رویداد شده، استفاده میکنید.
begin
if Sender is TButton then
begin
//do something if the button was clicked
end;
if Sender is TMenuItem then
begin
//do something if the menu item was clicked
end;
end;
با استفاده از کلمهی کلیدی is میتوانید نوع شیی از یک کلاس را در زمان اجرا بررسی کنید. "Sender is TButton" چک میکند که آیا پارامتر Sender یک TButton یا نوعی مشتق شده از TButton هست؟ . بعد از انجام عمل "چک" ، میتوانید شیء را به یک نوعی که نیاز دارید تبدیل کنید.
با hard-cast، به کامپایلر میگوئید که میدانید در انتظار چه شیی هستید. به همین خاطر hard-cast نا امن هست. برای دلفی جالب نخواهد بود اگر که یک نمونه از TEdit را به TButton با استفاده از hard-cast تبدیل کنید، مانند مثال زیر:
TButton(Edit1).Caption := 'junk code';
آیا این کد کار خواهد کرد؟ بله، کار خواهد کرد! با اینکه کلاس TEdit اصلاً ویژگی به نام Caption ندارد، اما تبدیل یک editbox به یک button، سپس تغییر ویژگی Caption آن button که نتیجهی آن، تغییر دادن ویژگی Text از شیء Edit1 خواهد بود. با استفاده از hard-cast میتوانید چنین تبدیلی انجام دهید.
از طرف دیگر، تبدیل امن as-cast باعث بوجود آمدن خطای EInvalidCast در این حالت خواهد شد، یعنی اگر به شکل زیر سعی در تبدیل عبارتی داشته باشید، با خطا مواجه میشوید :
//raises "Invalid Type Cast"
(Edit1 as TButton).Caption := 'junk code';
پیاده سازی Hard-Cast امن با استفاده از Is
غالب اوقات چنین کدی در دلفی پیدا خواهید کرد:
if Sender is TButton then
begin
TButton(Sender).DoSomething;
end;
در مثال بالا، با ترکیب عملگر is با hard-cast نا امن، یک تبدیل از نوع hard-cast امن خواهیم داشت.
بطو کلی شما میبایست از کد بالا استفاده کنید و نه عملگر is و در ادامهی آن as-cast، چونکه as-cast فقط زمان را مصرف میکند و مقدار زیادی سربار برای برنامه دارد، به این دلیل که کامپایلر ناگزیر به پیمودن زنجیر وار وراثت در RTL برای یافتن کلاس مشخصی ست تا بتواند شئ را به آن تبدیل کند و این زمانبر هست. فرض کنید میخواهید چندین بار کلاسی که دهمین وارث کلاس پدر خود هست را با AS-Cast تبدیل کنید، هربار ساختار سلسه مراتبی تا رسیدن به کلاسی که متد مورد نظر را داشته باشد طی میشود، حال ببینید چه سرباری میتواند برای برنامهی شما داشته باشد!؟ (به تصویر زیر دقت کنید). توسط کد بالا شما ابتدا بررسی میکنید که آیا Sender از نوع TButton هست یا خیر، و سپس با تبدیل (از نوع Hard Cast) میتوانید متد DoSomething را اجرا کنید.
http://img.majidonline.com/pic/91819/img1.jpg
فایل PDF همین مقاله را از لینک زیر میتوانید دریافت کنید: