PDA

View Full Version : سوال: تفاوت تعریف متغیر



Mask
دوشنبه 26 اردیبهشت 1390, 16:00 عصر
با سلام.
اگه یه متغیر رو در var فرم تعریف کنیم یا در public فرم ، چه فرقی با هم داره؟

یوسف زالی
دوشنبه 26 اردیبهشت 1390, 16:14 عصر
فرقش اینه که اگه var تو implementation باشه از فرم هایی که Use کردن دیده نمی شه.
اما اگه تو Public باشه به عنوان جزیی از فرم قابل مشاهده هست.
اگه تو interface تعریفش کنی هم دیده میشه اما مشمول قوانین کلاس ها نمی شه.
مثلا اگه از اون فرم یه مشتق بگیری یا ...
در کل بهتره کپسوله سازی رو رعایت کنی.
فرق دیگه و خیلی مهمش اینه که اگه تو Interface میذاری بدون اینکه فرم رو Create کنی به صرف Use کردن اون متغیر برات وجود داره.
اما تو Public اول باید فرم رو Create کرده باشی.

M_Maskout
دوشنبه 26 اردیبهشت 1390, 17:03 عصر
سلام
یونیت‌های کنترل کننده فرم قبل از اینکه کنترل کننده‌ی فرم باشن، یونیت هستند و یکی از کاربردهای یه یونیت اینه که کد برنامه قسمت بندی بشه و قسمت‌های مجزا از هم در کنار همدیگه تشکیل کل کاربرد (Applecation) رو بدن.
تعریف متغیر بیرون از یه کلاس باعث می‌شه تمام کلاس‌های تعریف شده در یه یونیت بتونن از به اون متغیر بدون هیچ دردسر و منعی دسترسی داشته باشن، ولی تعریف متغیر تو قسمت Public یه کلاس باعث می‌شه تا زمانی که کلاس ایجاد نشده، نشه به اون متغیر دسترسی داشت و ضمناً بعد از آزاد شدن کلاس، اون متغیر و مقدار اون از بین می‌ره. البته در صورت تعریف متغیر در قسمت Private فقط متدهای کلاس به اون متغیر دسترسی دارن که خود این اصولاً یه راه خوب برای کنترل مقدار دهی به متغیرهاست.
از نظر هزینه‌ی حافظه، متغیرهایی که در قسمت Var در بخش Interface یه یونیت ساخته می‌شن، بیشترین هزینه رو برای حافظه دارن. چون از زمانی که برنامه اجرا می‌شه تا زمانی که برنامه بسته می‌شه، به میزان طولی که دارن، حافظه اصلی سیستم رو اشغال می‌کنن. البته شاید این موضوع امروزه با اومدن حافظه‌های خیلی زیاد (1 گیگابایت یا حتی بیشتر) دیگه خیلی چیز پر اهمیتی جلوه نکنه. اما باز هم در صورت تعدد این جور متغیرها تو یه برنامه 20 یونیتی (و یا بیشتر) این قضیه می‌تونه مشکل ساز بشه. البته مدیریت متغیرهای سراسری هم خودش داستانیه که باید در نظر گرفته بشه. و علی القاعده تعریف متغیر تو بخش implementation می‌تونه یه کم مدیریت متغیرها رو راحتر کنه. هرچند در هزینه‌ی یاد شده شاید خیلی فرقی نکنه.
اما تعریف متغیر تو یه کلاس قطعاً از لحاظ هزینه، به صرفه تره. چون با ایجاد کلاس درست می‌شه و با آزاد شدن کلاس از بین می‌ره. ضمناً به صورت یه متغیر پویا ایجاد می‌شه و عملاً از حافظه اصلی خارجه.
احتمالاً امروزه تعریف متغیر و یا حتی روتین‌های سراسری (بی کلاس!) خیلی دیگه معمول نیست. الا برای کارای خاص (مثلاً یه سوئیچ در اجرای برنامه که کل قسمت‌های برنامه در صورت وجود اون یه جور دیگه عمل می‌کنن.) که در هر حالت در همه جای برنامه لازمه. البته فکر می‌کنم در این شرایط اصولاً استفاده از یه تعریف سراسری مجرد بهتر از تعریف یه کلاس سراسری باشه.

mbshareat
دوشنبه 26 اردیبهشت 1390, 22:56 عصر
با سلام
می بخشید یه سوال دارم:من یه متغیر رو تو Interface تعریف کردم و یونیت رو تو یه یونیت دیگه Use کردم.با ShowMessage می تونم محتوای متغیر رو ببینم.البته بدون نام یونیت مثل ShowMessage(IntToStr(A[2]));
آیا معنیش اینه که اگه متغیری با همون نام تو یونیت جاری هم باشه محتوای متغیر در یونیت جاری لحاظ میشه و اگه با پروسیجری در دو یونیت با عملکرد یکسان مقدار مشابه به متغیر بدیم کد اضافی تو برنامه نوشتیم(مثلا با پروسیجر ()SetA در هردو یونیت مقدار [A[2 رو N قرار بدیم)؟

SAASTN
دوشنبه 26 اردیبهشت 1390, 23:56 عصر
یه نکته در باب مقدار اولیه:
متغیر های سرارسری رو میشه مقدار دهی اولیه کرد (چه تو interface تعریف شده باشن چه تو implementation):
var
a: Integer = 20;

در صورتی که متغیر های محلی یا فیلدهای کلاس ها رو نمی شه مقدار دهی اولیه کرد.
فیلدها و متغیر های سراسری (درصورتی که صراحتا مقدار دهی اولیه نشده باشن) توسط کامپایلر صفر می شن، در صورتی که مقدار متغیر های محلی تا قبل از اولین مقدار دهی نا معلومه.

می تونم محتوای متغیر رو ببینم.البته بدون نام یونیت
در صورت همنام بودن دو متغیر (یا هر چیز دیگه ای) اونی که در Scope نزدیک تری هست مورد استفاده قرار می گیره. در این مثال در صورت عدم ذکر نام یونیت متغیری که در یونیت جاری تعریف شده مورد استفاده قرار می گیره. حالا اگه توی همون روالی که ShowMessage کردید هم یه متغیر یا حتی ثابت به نام A تعریف کنید، ShowMessage مقدار اون رو نمایش میده. حالا در این شرایط برای دسترسی به شناسه هایی که در Scope های دورتری تعریف شدن حتما باید نام NameSpaceی که اون شناسه درش تعریف شده رو ذکر کنید.
مثلا فرض کنید کلاس ما یه فیلد با نام X داره. از طرفی در یکی از روالهای همون کلاس یه متغیر با نام X تعریف شده. در اینجا چون روال Scope نزدیکتری هست، X به متغیر اشاره می کنه و اگر بخوایم در همین روال به فیلد X دسترسی پیدا کنیم باید از Self.X استفاده کنیم.

mbshareat
سه شنبه 27 اردیبهشت 1390, 00:32 صبح
با سلام
من نام یونیت دیگه که [2]A توش تعریف شده رو که میارم خطا میگیره!

SAASTN
سه شنبه 27 اردیبهشت 1390, 02:22 صبح
آقا شما دیگه چرا؟؟ بابا خوب بگید چه کدی زدینو و چه خطایی گرفتین ...
ببینید سوالی رو که می تونستید تو یه پست بپرسید و تو پست بعدی یکی بیاد جواب بده شد چهارتا پست:
- خطا داره!
- نه بابا؟! چه خطایی؟
- unit1.pas(125): WTF is going on?!
- آهان اینو که یک می زنی تو سرش می فهمه ...

یوسف زالی
سه شنبه 27 اردیبهشت 1390, 04:11 صبح
یه سورس برات می ذارم اشکالت احتمالا رفع شه.

Mahmood_M
سه شنبه 27 اردیبهشت 1390, 22:17 عصر
اگه یه متغیر رو در var فرم تعریف کنیم یا در public فرم ، چه فرقی با هم داره؟
صورت مسئله درست نیست !

فرم Var نداره ، فرم یک کلاس هست از نوع TForm که مثل هر کلاس دیگه ای در دلفی می تونه عضو داشته باشه ، وقتی متغیری در بدنه کلاس فرم ( Public یا Private یا ... ) تعریف میشه ، عضوی از اون کلاس هست و برای دسترسی به اون باید اول به کلاسش دسترسی داشته باشید ...
قسمت Var در یونیت غالبا برای از بین بردن همین محدودیت استفاده میشه ، یعنی تعریف متغیر ( یا ... ) ای که برای دسترسی به اون نیازی به دسترسی به کلاسی نباشه ، در واقع یک متغیر عمومی و بی صاحب ! در محدوده ی یونیت
این دو قسمت با هم قابل قیاس نیستند ...

SAASTN
سه شنبه 27 اردیبهشت 1390, 23:20 عصر
اگه یه متغیر رو در var فرم تعریف کنیم یا در public فرم ، چه فرقی با هم داره؟
آقا من تازه سوال تاپیک رو متوجه شدم!! احتمالا خیلی سریع از رو سوال رد شدم و پی جوابای دوستان رو گرفتم. در واقع احتمالا نگارش دقیقتر سوال این شکلی میشه: اگه یه فیلد رو در بخش var کلاس تعریف کنیم یا در public کلاس، چه فرقی با هم داره؟ اگرم منظورتون این نبوده که ببخشید.

To define a field member of a class, simply declare the field as you would a variable. For example, the following declaration creates a class called TNumber whose only member, other than the methods inherited from System.TObject, is an integer field called Int:

type
TNumber = class
var
Int: Integer;
end;

The var keyword is optional. However, if it is not used, then all field declarations must occur before any property or method declarations. After any property or method declarations, the var may be used to introduce any additional field declarations.

این جفنگیات رو تو راهنمای خود دلفی گفته. من چیزی که از این گفته ها می فهمم اینه که اون var تنها یه محدودیت سینتکسی رو برطرف میکنه. در واقع اصلا بخش var و public نداریم، بلکه اگه var نوشته بشه خودش یه زیر بخش از public، private و غیرست. حالا فرض کنید تو بخش private اگه var نباشه فیلدها حتما باید قبل از پراپرتی ها یا متدها تعریف بشن، اما اگه بخوایم تو همون بخش private بعد از تعریف متدها یا پراپرتی ها هم فیلد جدیدی تعریف کنیم باید یه var اضافه کنیم. اما اگه با تعریف فیلدها قبل از متدها و پراپرتی ها کارمون راه می افته دیگه ذکر کلمه var اختیاریه.

یوسف زالی
چهارشنبه 28 اردیبهشت 1390, 05:36 صبح
SAASTN جان منظور دوستمون اینه:


interface
var A:integer;
.
.
TForm1 = class(TFORM)
var B:Integer;.
.
end;

implementation
var C:Integer;
.
.



فرقای اینا رو می خواست.

SAASTN
چهارشنبه 28 اردیبهشت 1390, 07:29 صبح
والا من نمی تونم با این قطعیت نظر بدم، خوب منم اول برداشت شما رو داشتم و پاسخ قبلیم در همون راستا بود، ولی بعد از پاسخ آقا محمود که یبار دیگه متن سوال رو خوندم به این نتیجه رسیدم که متن جمله ایشون به این نزدیک تره:
TForm1 = class(TForm)
Button1: TButton;
var
A: Integer;
public
B: Integer;
end;

تصور می کنم یه همچین چیزی قرابت بیشتری به "var فرم" داره. البته بازم مطمئن نیستم و خود جناب Gold هم که غیر از متن سوال و چند تشکر موضعگیری دیگه ای نکردند. البته تفاوت چندانی هم نداره، چون تاپیک بیشتر جنبه گفتگو داره و خوب از جهات مختلف رو موضوع بحث شده.

یوسف زالی
چهارشنبه 28 اردیبهشت 1390, 08:22 صبح
اه آره.
حق با شماست و بی دقتی از ما.

Mask
چهارشنبه 28 اردیبهشت 1390, 10:31 صبح
ممنون از دوستان.
مفهوم سوالم رو آقا محمود در پستشون گفتند. و جواب دادند.
اما بقیه دوستان هم زحمت کشیدند و روشهای تعریف متغیر رو در قسمتهای دیگه گفتند که خیلی مفید بود.
بنده به جوابم رسیدم. ممنون از همه دوستان.